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.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))
206 mono_reflection_init (void)
211 sigbuffer_init (SigBuffer *buf, int size)
213 buf->buf = g_malloc (size);
215 buf->end = buf->buf + size;
219 sigbuffer_make_room (SigBuffer *buf, int size)
221 if (buf->end - buf->p < size) {
222 int new_size = buf->end - buf->buf + size + 32;
223 char *p = g_realloc (buf->buf, new_size);
224 size = buf->p - buf->buf;
227 buf->end = buf->buf + new_size;
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
234 sigbuffer_make_room (buf, 6);
235 mono_metadata_encode_value (val, buf->p, &buf->p);
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
241 sigbuffer_make_room (buf, 1);
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
249 sigbuffer_make_room (buf, size);
250 memcpy (buf->p, p, size);
255 sigbuffer_free (SigBuffer *buf)
260 #ifndef DISABLE_REFLECTION_EMIT
264 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
268 image_g_malloc (MonoImage *image, guint size)
271 return mono_image_alloc (image, size);
273 return g_malloc (size);
275 #endif /* !DISABLE_REFLECTION_EMIT */
280 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
284 image_g_malloc0 (MonoImage *image, guint size)
287 return mono_image_alloc0 (image, size);
289 return g_malloc0 (size);
292 #ifndef DISABLE_REFLECTION_EMIT
294 image_strdup (MonoImage *image, const char *s)
297 return mono_image_strdup (image, s);
303 #define image_g_new(image,struct_type, n_structs) \
304 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
306 #define image_g_new0(image,struct_type, n_structs) \
307 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
311 alloc_table (MonoDynamicTable *table, guint nrows)
314 g_assert (table->columns);
315 if (nrows + 1 >= table->alloc_rows) {
316 while (nrows + 1 >= table->alloc_rows) {
317 if (table->alloc_rows == 0)
318 table->alloc_rows = 16;
320 table->alloc_rows *= 2;
323 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
328 make_room_in_stream (MonoDynamicStream *stream, int size)
330 if (size <= stream->alloc_size)
333 while (stream->alloc_size <= size) {
334 if (stream->alloc_size < 4096)
335 stream->alloc_size = 4096;
337 stream->alloc_size *= 2;
340 stream->data = g_realloc (stream->data, stream->alloc_size);
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
348 gpointer oldkey, oldval;
350 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351 return GPOINTER_TO_UINT (oldval);
353 len = strlen (str) + 1;
356 make_room_in_stream (sh, idx + len);
359 * We strdup the string even if we already copy them in sh->data
360 * so that the string pointers in the hash remain valid even if
361 * we need to realloc sh->data. We may want to avoid that later.
363 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364 memcpy (sh->data + idx, str, len);
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
372 char *name = mono_string_to_utf8 (str);
374 idx = string_heap_insert (sh, name);
379 #ifndef DISABLE_REFLECTION_EMIT
381 string_heap_init (MonoDynamicStream *sh)
384 sh->alloc_size = 4096;
385 sh->data = g_malloc (4096);
386 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387 string_heap_insert (sh, "");
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
396 make_room_in_stream (stream, stream->index + len);
397 memcpy (stream->data + stream->index, data, len);
399 stream->index += len;
401 * align index? Not without adding an additional param that controls it since
402 * we may store a blob value in pieces.
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
412 make_room_in_stream (stream, stream->index + len);
413 memset (stream->data + stream->index, 0, len);
415 stream->index += len;
420 stream_data_align (MonoDynamicStream *stream)
423 guint32 count = stream->index % 4;
425 /* we assume the stream data will be aligned */
427 mono_image_add_stream_data (stream, buf, 4 - count);
430 #ifndef DISABLE_REFLECTION_EMIT
432 mono_blob_entry_hash (const char* str)
436 len = mono_metadata_decode_blob_size (str, &str);
440 for (str += 1; str < end; str++)
441 h = (h << 5) - h + *str;
449 mono_blob_entry_equal (const char *str1, const char *str2) {
453 len = mono_metadata_decode_blob_size (str1, &end1);
454 len2 = mono_metadata_decode_blob_size (str2, &end2);
457 return memcmp (end1, end2, len) == 0;
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
465 gpointer oldkey, oldval;
467 copy = g_malloc (s1+s2);
468 memcpy (copy, b1, s1);
469 memcpy (copy + s1, b2, s2);
470 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
472 idx = GPOINTER_TO_UINT (oldval);
474 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475 mono_image_add_stream_data (&assembly->blob, b2, s2);
476 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
486 guint32 size = buf->p - buf->buf;
488 g_assert (size <= (buf->end - buf->buf));
489 mono_metadata_encode_value (size, b, &b);
490 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
494 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495 * dest may be misaligned.
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
502 for (elem = 0; elem < nelem; ++elem) {
528 g_assert_not_reached ();
534 memcpy (dest, val, len * nelem);
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
543 guint32 idx = 0, len;
545 len = str->length * 2;
546 mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
549 char *swapped = g_malloc (2 * mono_string_length (str));
550 const char *p = (const char*)mono_string_chars (str);
552 swap_with_size (swapped, p, 2, mono_string_length (str));
553 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
557 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
562 #ifndef DISABLE_REFLECTION_EMIT
564 default_class_from_mono_type (MonoType *type)
566 switch (type->type) {
567 case MONO_TYPE_OBJECT:
568 return mono_defaults.object_class;
570 return mono_defaults.void_class;
571 case MONO_TYPE_BOOLEAN:
572 return mono_defaults.boolean_class;
574 return mono_defaults.char_class;
576 return mono_defaults.sbyte_class;
578 return mono_defaults.byte_class;
580 return mono_defaults.int16_class;
582 return mono_defaults.uint16_class;
584 return mono_defaults.int32_class;
586 return mono_defaults.uint32_class;
588 return mono_defaults.int_class;
590 return mono_defaults.uint_class;
592 return mono_defaults.int64_class;
594 return mono_defaults.uint64_class;
596 return mono_defaults.single_class;
598 return mono_defaults.double_class;
599 case MONO_TYPE_STRING:
600 return mono_defaults.string_class;
602 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603 g_assert_not_reached ();
611 * mono_class_get_ref_info:
613 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
616 mono_class_get_ref_info (MonoClass *klass)
618 if (klass->ref_info_handle == 0)
621 return mono_gchandle_get_target (klass->ref_info_handle);
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
627 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628 g_assert (klass->ref_info_handle != 0);
632 mono_class_free_ref_info (MonoClass *klass)
634 if (klass->ref_info_handle) {
635 mono_gchandle_free (klass->ref_info_handle);
636 klass->ref_info_handle = 0;
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
644 MonoGenericInst *class_inst;
649 class_inst = gclass->context.class_inst;
651 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652 klass = gclass->container_class;
653 sigbuffer_add_value (buf, klass->byval_arg.type);
654 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
656 sigbuffer_add_value (buf, class_inst->type_argc);
657 for (i = 0; i < class_inst->type_argc; ++i)
658 encode_type (assembly, class_inst->type_argv [i], buf);
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
666 g_assert_not_reached ();
671 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
675 case MONO_TYPE_BOOLEAN:
689 case MONO_TYPE_STRING:
690 case MONO_TYPE_OBJECT:
691 case MONO_TYPE_TYPEDBYREF:
692 sigbuffer_add_value (buf, type->type);
695 sigbuffer_add_value (buf, type->type);
696 encode_type (assembly, type->data.type, buf);
698 case MONO_TYPE_SZARRAY:
699 sigbuffer_add_value (buf, type->type);
700 encode_type (assembly, &type->data.klass->byval_arg, buf);
702 case MONO_TYPE_VALUETYPE:
703 case MONO_TYPE_CLASS: {
704 MonoClass *k = mono_class_from_mono_type (type);
706 if (k->generic_container) {
707 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708 encode_generic_class (assembly, gclass, buf);
711 * Make sure we use the correct type.
713 sigbuffer_add_value (buf, k->byval_arg.type);
715 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716 * otherwise two typerefs could point to the same type, leading to
717 * verification errors.
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
723 case MONO_TYPE_ARRAY:
724 sigbuffer_add_value (buf, type->type);
725 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726 sigbuffer_add_value (buf, type->data.array->rank);
727 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728 sigbuffer_add_value (buf, 0);
730 case MONO_TYPE_GENERICINST:
731 encode_generic_class (assembly, type->data.generic_class, buf);
735 sigbuffer_add_value (buf, type->type);
736 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
739 g_error ("need to encode type %x", type->type);
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
747 sigbuffer_add_value (buf, MONO_TYPE_VOID);
751 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
760 for (i = 0; i < mono_array_length (modreq); ++i) {
761 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
767 for (i = 0; i < mono_array_length (modopt); ++i) {
768 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
775 #ifndef DISABLE_REFLECTION_EMIT
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
781 guint32 nparams = sig->param_count;
787 sigbuffer_init (&buf, 32);
789 * FIXME: vararg, explicit_this, differenc call_conv values...
791 idx = sig->call_convention;
793 idx |= 0x20; /* hasthis */
794 if (sig->generic_param_count)
795 idx |= 0x10; /* generic */
796 sigbuffer_add_byte (&buf, idx);
797 if (sig->generic_param_count)
798 sigbuffer_add_value (&buf, sig->generic_param_count);
799 sigbuffer_add_value (&buf, nparams);
800 encode_type (assembly, sig->ret, &buf);
801 for (i = 0; i < nparams; ++i) {
802 if (i == sig->sentinelpos)
803 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804 encode_type (assembly, sig->params [i], &buf);
806 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807 sigbuffer_free (&buf);
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
816 * FIXME: reuse code from method_encode_signature().
820 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
821 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
825 sigbuffer_init (&buf, 32);
826 /* LAMESPEC: all the call conv spec is foobared */
827 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828 if (mb->call_conv & 2)
829 idx |= 0x5; /* vararg */
830 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831 idx |= 0x20; /* hasthis */
833 idx |= 0x10; /* generic */
834 sigbuffer_add_byte (&buf, idx);
836 sigbuffer_add_value (&buf, ngparams);
837 sigbuffer_add_value (&buf, nparams + notypes);
838 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839 encode_reflection_type (assembly, mb->rtype, &buf);
840 for (i = 0; i < nparams; ++i) {
841 MonoArray *modreq = NULL;
842 MonoArray *modopt = NULL;
843 MonoReflectionType *pt;
845 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851 encode_reflection_type (assembly, pt, &buf);
854 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855 for (i = 0; i < notypes; ++i) {
856 MonoReflectionType *pt;
858 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859 encode_reflection_type (assembly, pt, &buf);
862 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863 sigbuffer_free (&buf);
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
870 MonoDynamicTable *table;
872 guint32 idx, sig_idx;
873 guint nl = mono_array_length (ilgen->locals);
877 sigbuffer_init (&buf, 32);
878 sigbuffer_add_value (&buf, 0x07);
879 sigbuffer_add_value (&buf, nl);
880 for (i = 0; i < nl; ++i) {
881 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
884 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
886 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
888 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889 sigbuffer_free (&buf);
891 if (assembly->standalonesig_cache == NULL)
892 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
897 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898 idx = table->next_idx ++;
900 alloc_table (table, table->rows);
901 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
903 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
905 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
911 method_count_clauses (MonoReflectionILGen *ilgen)
913 guint32 num_clauses = 0;
916 MonoILExceptionInfo *ex_info;
917 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919 if (ex_info->handlers)
920 num_clauses += mono_array_length (ex_info->handlers);
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
932 MonoExceptionClause *clauses;
933 MonoExceptionClause *clause;
934 MonoILExceptionInfo *ex_info;
935 MonoILExceptionBlock *ex_block;
936 guint32 finally_start;
937 int i, j, clause_index;;
939 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
942 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944 finally_start = ex_info->start + ex_info->len;
945 if (!ex_info->handlers)
947 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949 clause = &(clauses [clause_index]);
951 clause->flags = ex_block->type;
952 clause->try_offset = ex_info->start;
954 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955 clause->try_len = finally_start - ex_info->start;
957 clause->try_len = ex_info->len;
958 clause->handler_offset = ex_block->start;
959 clause->handler_len = ex_block->len;
960 if (ex_block->extype) {
961 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
963 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964 clause->data.filter_offset = ex_block->filter_offset;
966 clause->data.filter_offset = 0;
968 finally_start = ex_block->start + ex_block->len;
976 #endif /* !DISABLE_REFLECTION_EMIT */
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
985 gint32 num_locals = 0;
986 gint32 num_exception = 0;
989 char fat_header [12];
992 guint32 local_sig = 0;
993 guint32 header_size = 12;
996 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1001 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1003 code = mb->ilgen->code;
1004 code_size = mb->ilgen->code_len;
1005 max_stack = mb->ilgen->max_stack;
1006 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007 if (mb->ilgen->ex_handlers)
1008 num_exception = method_count_clauses (mb->ilgen);
1012 char *name = mono_string_to_utf8 (mb->name);
1013 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1017 mono_raise_exception (exception);
1020 code_size = mono_array_length (code);
1021 max_stack = 8; /* we probably need to run a verifier on the code... */
1024 stream_data_align (&assembly->code);
1026 /* check for exceptions, maxstack, locals */
1027 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1029 if (code_size < 64 && !(code_size & 1)) {
1030 flags = (code_size << 2) | 0x2;
1031 } else if (code_size < 32 && (code_size & 1)) {
1032 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1036 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1037 /* add to the fixup todo list */
1038 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1040 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041 return assembly->text_rva + idx;
1045 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1047 * FIXME: need to set also the header size in fat_flags.
1048 * (and more sects and init locals flags)
1052 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053 if (mb->init_locals)
1054 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055 fat_header [0] = fat_flags;
1056 fat_header [1] = (header_size / 4 ) << 4;
1057 short_value = GUINT16_TO_LE (max_stack);
1058 memcpy (fat_header + 2, &short_value, 2);
1059 int_value = GUINT32_TO_LE (code_size);
1060 memcpy (fat_header + 4, &int_value, 4);
1061 int_value = GUINT32_TO_LE (local_sig);
1062 memcpy (fat_header + 8, &int_value, 4);
1063 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064 /* add to the fixup todo list */
1065 if (mb->ilgen && mb->ilgen->num_token_fixups)
1066 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1068 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069 if (num_exception) {
1070 unsigned char sheader [4];
1071 MonoILExceptionInfo * ex_info;
1072 MonoILExceptionBlock * ex_block;
1075 stream_data_align (&assembly->code);
1076 /* always use fat format for now */
1077 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078 num_exception *= 6 * sizeof (guint32);
1079 num_exception += 4; /* include the size of the header */
1080 sheader [1] = num_exception & 0xff;
1081 sheader [2] = (num_exception >> 8) & 0xff;
1082 sheader [3] = (num_exception >> 16) & 0xff;
1083 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084 /* fat header, so we are already aligned */
1086 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088 if (ex_info->handlers) {
1089 int finally_start = ex_info->start + ex_info->len;
1090 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1092 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1094 val = GUINT32_TO_LE (ex_block->type);
1095 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1097 val = GUINT32_TO_LE (ex_info->start);
1098 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099 /* need fault, too, probably */
1100 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101 val = GUINT32_TO_LE (finally_start - ex_info->start);
1103 val = GUINT32_TO_LE (ex_info->len);
1104 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105 /* handler offset */
1106 val = GUINT32_TO_LE (ex_block->start);
1107 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109 val = GUINT32_TO_LE (ex_block->len);
1110 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111 finally_start = ex_block->start + ex_block->len;
1112 if (ex_block->extype) {
1113 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1115 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116 val = ex_block->filter_offset;
1120 val = GUINT32_TO_LE (val);
1121 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122 /*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",
1123 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);*/
1126 g_error ("No clauses for ex info block %d", i);
1130 return assembly->text_rva + idx;
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1137 MonoDynamicTable *table;
1140 table = &assembly->tables [table_idx];
1142 g_assert (col < table->columns);
1144 values = table->values + table->columns;
1145 for (i = 1; i <= table->rows; ++i) {
1146 if (values [col] == token)
1148 values += table->columns;
1154 * LOCKING: Acquires the loader lock.
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1159 MonoCustomAttrInfo* res;
1161 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1166 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1174 /* FIXME: Need to do more checks */
1175 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1178 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1188 int i, index, count, not_visible;
1189 MonoCustomAttrInfo *ainfo;
1190 MonoReflectionCustomAttr *cattr;
1194 /* FIXME: check in assembly the Run flag is set */
1196 count = mono_array_length (cattrs);
1198 /* Skip nonpublic attributes since MS.NET seems to do the same */
1199 /* FIXME: This needs to be done more globally */
1201 for (i = 0; i < count; ++i) {
1202 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203 if (!custom_attr_visible (image, cattr))
1206 count -= not_visible;
1208 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1210 ainfo->image = image;
1211 ainfo->num_attrs = count;
1212 ainfo->cached = alloc_img != NULL;
1214 for (i = 0; i < count; ++i) {
1215 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216 if (custom_attr_visible (image, cattr)) {
1217 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219 ainfo->attrs [index].ctor = cattr->ctor->method;
1220 ainfo->attrs [index].data = saved;
1221 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1229 #ifndef DISABLE_REFLECTION_EMIT
1231 * LOCKING: Acquires the loader lock.
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1236 MonoCustomAttrInfo *ainfo, *tmp;
1238 if (!cattrs || !mono_array_length (cattrs))
1241 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1243 mono_loader_lock ();
1244 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1246 mono_custom_attrs_free (tmp);
1247 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248 mono_loader_unlock ();
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1261 * idx is the table index of the object
1262 * type is one of MONO_CUSTOM_ATTR_*
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1267 MonoDynamicTable *table;
1268 MonoReflectionCustomAttr *cattr;
1270 guint32 count, i, token;
1272 char *p = blob_size;
1274 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1277 count = mono_array_length (cattrs);
1278 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279 table->rows += count;
1280 alloc_table (table, table->rows);
1281 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282 idx <<= MONO_CUSTOM_ATTR_BITS;
1284 for (i = 0; i < count; ++i) {
1285 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288 type = mono_metadata_token_index (token);
1289 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290 switch (mono_metadata_token_table (token)) {
1291 case MONO_TABLE_METHOD:
1292 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1294 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1295 * method, not the one returned by mono_image_create_token ().
1297 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1299 case MONO_TABLE_MEMBERREF:
1300 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1303 g_warning ("got wrong token in custom attr");
1306 values [MONO_CUSTOM_ATTR_TYPE] = type;
1308 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1309 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1310 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1311 values += MONO_CUSTOM_ATTR_SIZE;
1317 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1319 MonoDynamicTable *table;
1321 guint32 count, i, idx;
1322 MonoReflectionPermissionSet *perm;
1327 count = mono_array_length (permissions);
1328 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1329 table->rows += count;
1330 alloc_table (table, table->rows);
1332 for (i = 0; i < mono_array_length (permissions); ++i) {
1333 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1335 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1337 idx = mono_metadata_token_index (parent_token);
1338 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1339 switch (mono_metadata_token_table (parent_token)) {
1340 case MONO_TABLE_TYPEDEF:
1341 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1343 case MONO_TABLE_METHOD:
1344 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1346 case MONO_TABLE_ASSEMBLY:
1347 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1350 g_assert_not_reached ();
1353 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1354 values [MONO_DECL_SECURITY_PARENT] = idx;
1355 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1362 * Fill in the MethodDef and ParamDef tables for a method.
1363 * This is used for both normal methods and constructors.
1366 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1368 MonoDynamicTable *table;
1372 /* room in this table is already allocated */
1373 table = &assembly->tables [MONO_TABLE_METHOD];
1374 *mb->table_idx = table->next_idx ++;
1375 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1376 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1377 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1378 values [MONO_METHOD_FLAGS] = mb->attrs;
1379 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1380 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1381 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1383 table = &assembly->tables [MONO_TABLE_PARAM];
1384 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1386 mono_image_add_decl_security (assembly,
1387 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1390 MonoDynamicTable *mtable;
1393 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1394 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1397 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1398 if (mono_array_get (mb->pinfo, gpointer, i))
1401 table->rows += count;
1402 alloc_table (table, table->rows);
1403 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1404 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1405 MonoReflectionParamBuilder *pb;
1406 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1407 values [MONO_PARAM_FLAGS] = pb->attrs;
1408 values [MONO_PARAM_SEQUENCE] = i;
1409 if (pb->name != NULL) {
1410 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1412 values [MONO_PARAM_NAME] = 0;
1414 values += MONO_PARAM_SIZE;
1415 if (pb->marshal_info) {
1417 alloc_table (mtable, mtable->rows);
1418 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1419 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1420 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1422 pb->table_idx = table->next_idx++;
1423 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1424 guint32 field_type = 0;
1425 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1427 alloc_table (mtable, mtable->rows);
1428 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1429 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1430 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1431 mvalues [MONO_CONSTANT_TYPE] = field_type;
1432 mvalues [MONO_CONSTANT_PADDING] = 0;
1439 #ifndef DISABLE_REFLECTION_EMIT
1441 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1443 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1445 rmb->ilgen = mb->ilgen;
1446 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1447 rmb->parameters = mb->parameters;
1448 rmb->generic_params = mb->generic_params;
1449 rmb->generic_container = mb->generic_container;
1450 rmb->opt_types = NULL;
1451 rmb->pinfo = mb->pinfo;
1452 rmb->attrs = mb->attrs;
1453 rmb->iattrs = mb->iattrs;
1454 rmb->call_conv = mb->call_conv;
1455 rmb->code = mb->code;
1456 rmb->type = mb->type;
1457 rmb->name = mb->name;
1458 rmb->table_idx = &mb->table_idx;
1459 rmb->init_locals = mb->init_locals;
1460 rmb->skip_visibility = FALSE;
1461 rmb->return_modreq = mb->return_modreq;
1462 rmb->return_modopt = mb->return_modopt;
1463 rmb->param_modreq = mb->param_modreq;
1464 rmb->param_modopt = mb->param_modopt;
1465 rmb->permissions = mb->permissions;
1466 rmb->mhandle = mb->mhandle;
1471 rmb->charset = mb->charset;
1472 rmb->extra_flags = mb->extra_flags;
1473 rmb->native_cc = mb->native_cc;
1474 rmb->dllentry = mb->dllentry;
1480 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1482 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1484 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1486 rmb->ilgen = mb->ilgen;
1487 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1488 rmb->parameters = mb->parameters;
1489 rmb->generic_params = NULL;
1490 rmb->generic_container = NULL;
1491 rmb->opt_types = NULL;
1492 rmb->pinfo = mb->pinfo;
1493 rmb->attrs = mb->attrs;
1494 rmb->iattrs = mb->iattrs;
1495 rmb->call_conv = mb->call_conv;
1497 rmb->type = mb->type;
1498 rmb->name = mono_string_new (mono_domain_get (), name);
1499 rmb->table_idx = &mb->table_idx;
1500 rmb->init_locals = mb->init_locals;
1501 rmb->skip_visibility = FALSE;
1502 rmb->return_modreq = NULL;
1503 rmb->return_modopt = NULL;
1504 rmb->param_modreq = mb->param_modreq;
1505 rmb->param_modopt = mb->param_modopt;
1506 rmb->permissions = mb->permissions;
1507 rmb->mhandle = mb->mhandle;
1513 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1515 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1517 rmb->ilgen = mb->ilgen;
1518 rmb->rtype = mb->rtype;
1519 rmb->parameters = mb->parameters;
1520 rmb->generic_params = NULL;
1521 rmb->generic_container = NULL;
1522 rmb->opt_types = NULL;
1524 rmb->attrs = mb->attrs;
1526 rmb->call_conv = mb->call_conv;
1528 rmb->type = (MonoObject *) mb->owner;
1529 rmb->name = mb->name;
1530 rmb->table_idx = NULL;
1531 rmb->init_locals = mb->init_locals;
1532 rmb->skip_visibility = mb->skip_visibility;
1533 rmb->return_modreq = NULL;
1534 rmb->return_modopt = NULL;
1535 rmb->param_modreq = NULL;
1536 rmb->param_modopt = NULL;
1537 rmb->permissions = NULL;
1538 rmb->mhandle = mb->mhandle;
1545 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1547 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1548 MonoDynamicTable *table;
1551 MonoReflectionMethod *m;
1554 if (!mb->override_methods)
1557 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1558 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1560 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1562 alloc_table (table, table->rows);
1563 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1564 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1565 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1567 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1568 switch (mono_metadata_token_table (tok)) {
1569 case MONO_TABLE_MEMBERREF:
1570 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1572 case MONO_TABLE_METHOD:
1573 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1576 g_assert_not_reached ();
1578 values [MONO_METHODIMPL_DECLARATION] = tok;
1582 #ifndef DISABLE_REFLECTION_EMIT
1584 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1586 MonoDynamicTable *table;
1588 ReflectionMethodBuilder rmb;
1591 reflection_methodbuilder_from_method_builder (&rmb, mb);
1593 mono_image_basic_method (&rmb, assembly);
1594 mb->table_idx = *rmb.table_idx;
1596 if (mb->dll) { /* It's a P/Invoke method */
1598 /* map CharSet values to on-disk values */
1599 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1600 int extra_flags = mb->extra_flags;
1601 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1603 alloc_table (table, table->rows);
1604 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1606 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1607 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1609 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1611 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1612 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1613 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1614 table = &assembly->tables [MONO_TABLE_MODULEREF];
1616 alloc_table (table, table->rows);
1617 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1618 values [MONO_IMPLMAP_SCOPE] = table->rows;
1622 if (mb->generic_params) {
1623 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1624 table->rows += mono_array_length (mb->generic_params);
1625 alloc_table (table, table->rows);
1626 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1627 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1629 mono_image_get_generic_param_info (
1630 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1637 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1639 ReflectionMethodBuilder rmb;
1641 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1643 mono_image_basic_method (&rmb, assembly);
1644 mb->table_idx = *rmb.table_idx;
1649 type_get_fully_qualified_name (MonoType *type)
1651 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1655 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1659 klass = mono_class_from_mono_type (type);
1661 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1662 ta = klass->image->assembly;
1663 if (ta->dynamic || (ta == ass)) {
1664 if (klass->generic_class || klass->generic_container)
1665 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1666 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1668 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1671 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 /*field_image is the image to which the eventual custom mods have been encoded against*/
1677 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1680 guint32 idx, i, token;
1682 if (!assembly->save)
1685 sigbuffer_init (&buf, 32);
1687 sigbuffer_add_value (&buf, 0x06);
1688 /* encode custom attributes before the type */
1689 if (type->num_mods) {
1690 for (i = 0; i < type->num_mods; ++i) {
1692 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1694 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1696 token = type->modifiers [i].token;
1699 if (type->modifiers [i].required)
1700 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1702 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1704 sigbuffer_add_value (&buf, token);
1707 encode_type (assembly, type, &buf);
1708 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1709 sigbuffer_free (&buf);
1715 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1719 guint32 typespec = 0;
1723 init_type_builder_generics (fb->type);
1725 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1726 class = mono_class_from_mono_type (type);
1728 sigbuffer_init (&buf, 32);
1730 sigbuffer_add_value (&buf, 0x06);
1731 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1732 /* encode custom attributes before the type */
1734 if (class->generic_container)
1735 typespec = create_typespec (assembly, type);
1738 MonoGenericClass *gclass;
1739 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1740 encode_generic_class (assembly, gclass, &buf);
1742 encode_type (assembly, type, &buf);
1744 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1745 sigbuffer_free (&buf);
1750 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1751 char blob_size [64];
1752 char *b = blob_size;
1755 guint32 idx = 0, len = 0, dummy = 0;
1757 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1758 guint32 fpa_double [2];
1763 p = buf = g_malloc (64);
1765 *ret_type = MONO_TYPE_CLASS;
1767 box_val = (char*)&dummy;
1769 box_val = ((char*)val) + sizeof (MonoObject);
1770 *ret_type = val->vtable->klass->byval_arg.type;
1773 switch (*ret_type) {
1774 case MONO_TYPE_BOOLEAN:
1779 case MONO_TYPE_CHAR:
1796 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1797 fpa_p = (guint32*)box_val;
1798 fpa_double [0] = fpa_p [1];
1799 fpa_double [1] = fpa_p [0];
1800 box_val = (char*)fpa_double;
1804 case MONO_TYPE_VALUETYPE: {
1805 MonoClass *klass = val->vtable->klass;
1807 if (klass->enumtype) {
1808 *ret_type = mono_class_enum_basetype (klass)->type;
1810 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1813 g_error ("we can't encode valuetypes, we should have never reached this line");
1816 case MONO_TYPE_CLASS:
1818 case MONO_TYPE_STRING: {
1819 MonoString *str = (MonoString*)val;
1820 /* there is no signature */
1821 len = str->length * 2;
1822 mono_metadata_encode_value (len, b, &b);
1823 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1825 char *swapped = g_malloc (2 * mono_string_length (str));
1826 const char *p = (const char*)mono_string_chars (str);
1828 swap_with_size (swapped, p, 2, mono_string_length (str));
1829 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1833 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1839 case MONO_TYPE_GENERICINST:
1840 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1843 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1846 /* there is no signature */
1847 mono_metadata_encode_value (len, b, &b);
1848 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1849 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1850 swap_with_size (blob_size, box_val, len, 1);
1851 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1853 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1861 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1866 sigbuffer_init (&buf, 32);
1868 sigbuffer_add_value (&buf, minfo->type);
1870 switch (minfo->type) {
1871 case MONO_NATIVE_BYVALTSTR:
1872 case MONO_NATIVE_BYVALARRAY:
1873 sigbuffer_add_value (&buf, minfo->count);
1875 case MONO_NATIVE_LPARRAY:
1876 if (minfo->eltype || minfo->has_size) {
1877 sigbuffer_add_value (&buf, minfo->eltype);
1878 if (minfo->has_size) {
1879 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1880 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1882 /* LAMESPEC: ElemMult is undocumented */
1883 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1887 case MONO_NATIVE_SAFEARRAY:
1889 sigbuffer_add_value (&buf, minfo->eltype);
1891 case MONO_NATIVE_CUSTOM:
1893 str = mono_string_to_utf8 (minfo->guid);
1895 sigbuffer_add_value (&buf, len);
1896 sigbuffer_add_mem (&buf, str, len);
1899 sigbuffer_add_value (&buf, 0);
1901 /* native type name */
1902 sigbuffer_add_value (&buf, 0);
1903 /* custom marshaler type name */
1904 if (minfo->marshaltype || minfo->marshaltyperef) {
1905 if (minfo->marshaltyperef)
1906 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1908 str = mono_string_to_utf8 (minfo->marshaltype);
1910 sigbuffer_add_value (&buf, len);
1911 sigbuffer_add_mem (&buf, str, len);
1914 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1915 sigbuffer_add_value (&buf, 0);
1917 if (minfo->mcookie) {
1918 str = mono_string_to_utf8 (minfo->mcookie);
1920 sigbuffer_add_value (&buf, len);
1921 sigbuffer_add_mem (&buf, str, len);
1924 sigbuffer_add_value (&buf, 0);
1930 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1931 sigbuffer_free (&buf);
1936 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1938 MonoDynamicTable *table;
1941 /* maybe this fixup should be done in the C# code */
1942 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1943 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1944 table = &assembly->tables [MONO_TABLE_FIELD];
1945 fb->table_idx = table->next_idx ++;
1946 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1947 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1948 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1949 values [MONO_FIELD_FLAGS] = fb->attrs;
1950 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1952 if (fb->offset != -1) {
1953 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1955 alloc_table (table, table->rows);
1956 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1957 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1958 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1960 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1961 guint32 field_type = 0;
1962 table = &assembly->tables [MONO_TABLE_CONSTANT];
1964 alloc_table (table, table->rows);
1965 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1966 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1967 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1968 values [MONO_CONSTANT_TYPE] = field_type;
1969 values [MONO_CONSTANT_PADDING] = 0;
1971 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1973 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1975 alloc_table (table, table->rows);
1976 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1977 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1979 * We store it in the code section because it's simpler for now.
1982 if (mono_array_length (fb->rva_data) >= 10)
1983 stream_data_align (&assembly->code);
1984 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1986 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1987 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1989 if (fb->marshal_info) {
1990 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1992 alloc_table (table, table->rows);
1993 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1994 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1995 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2000 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2003 guint32 nparams = 0;
2004 MonoReflectionMethodBuilder *mb = fb->get_method;
2005 MonoReflectionMethodBuilder *smb = fb->set_method;
2008 if (mb && mb->parameters)
2009 nparams = mono_array_length (mb->parameters);
2010 if (!mb && smb && smb->parameters)
2011 nparams = mono_array_length (smb->parameters) - 1;
2012 sigbuffer_init (&buf, 32);
2013 if (fb->call_conv & 0x20)
2014 sigbuffer_add_byte (&buf, 0x28);
2016 sigbuffer_add_byte (&buf, 0x08);
2017 sigbuffer_add_value (&buf, nparams);
2019 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2020 for (i = 0; i < nparams; ++i) {
2021 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2022 encode_reflection_type (assembly, pt, &buf);
2024 } else if (smb && smb->parameters) {
2025 /* the property type is the last param */
2026 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2027 for (i = 0; i < nparams; ++i) {
2028 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2029 encode_reflection_type (assembly, pt, &buf);
2032 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2035 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2036 sigbuffer_free (&buf);
2041 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2043 MonoDynamicTable *table;
2045 guint num_methods = 0;
2049 * we need to set things in the following tables:
2050 * PROPERTYMAP (info already filled in _get_type_info ())
2051 * PROPERTY (rows already preallocated in _get_type_info ())
2052 * METHOD (method info already done with the generic method code)
2056 table = &assembly->tables [MONO_TABLE_PROPERTY];
2057 pb->table_idx = table->next_idx ++;
2058 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2059 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2060 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2061 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2063 /* FIXME: we still don't handle 'other' methods */
2064 if (pb->get_method) num_methods ++;
2065 if (pb->set_method) num_methods ++;
2067 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2068 table->rows += num_methods;
2069 alloc_table (table, table->rows);
2071 if (pb->get_method) {
2072 semaidx = table->next_idx ++;
2073 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2074 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2075 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2076 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2078 if (pb->set_method) {
2079 semaidx = table->next_idx ++;
2080 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2081 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2082 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2083 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2085 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2086 guint32 field_type = 0;
2087 table = &assembly->tables [MONO_TABLE_CONSTANT];
2089 alloc_table (table, table->rows);
2090 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2091 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2092 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2093 values [MONO_CONSTANT_TYPE] = field_type;
2094 values [MONO_CONSTANT_PADDING] = 0;
2099 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2101 MonoDynamicTable *table;
2103 guint num_methods = 0;
2107 * we need to set things in the following tables:
2108 * EVENTMAP (info already filled in _get_type_info ())
2109 * EVENT (rows already preallocated in _get_type_info ())
2110 * METHOD (method info already done with the generic method code)
2113 table = &assembly->tables [MONO_TABLE_EVENT];
2114 eb->table_idx = table->next_idx ++;
2115 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2116 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2117 values [MONO_EVENT_FLAGS] = eb->attrs;
2118 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2121 * FIXME: we still don't handle 'other' methods
2123 if (eb->add_method) num_methods ++;
2124 if (eb->remove_method) num_methods ++;
2125 if (eb->raise_method) num_methods ++;
2127 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2128 table->rows += num_methods;
2129 alloc_table (table, table->rows);
2131 if (eb->add_method) {
2132 semaidx = table->next_idx ++;
2133 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2135 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2136 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2138 if (eb->remove_method) {
2139 semaidx = table->next_idx ++;
2140 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2141 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2142 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2143 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2145 if (eb->raise_method) {
2146 semaidx = table->next_idx ++;
2147 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2148 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2149 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2150 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2155 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2157 MonoDynamicTable *table;
2158 guint32 num_constraints, i;
2162 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2163 num_constraints = gparam->iface_constraints ?
2164 mono_array_length (gparam->iface_constraints) : 0;
2165 table->rows += num_constraints;
2166 if (gparam->base_type)
2168 alloc_table (table, table->rows);
2170 if (gparam->base_type) {
2171 table_idx = table->next_idx ++;
2172 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176 assembly, mono_reflection_type_get_handle (gparam->base_type));
2179 for (i = 0; i < num_constraints; i++) {
2180 MonoReflectionType *constraint = mono_array_get (
2181 gparam->iface_constraints, gpointer, i);
2183 table_idx = table->next_idx ++;
2184 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2186 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2187 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2188 assembly, mono_reflection_type_get_handle (constraint));
2193 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2195 GenericParamTableEntry *entry;
2198 * The GenericParam table must be sorted according to the `owner' field.
2199 * We need to do this sorting prior to writing the GenericParamConstraint
2200 * table, since we have to use the final GenericParam table indices there
2201 * and they must also be sorted.
2204 entry = g_new0 (GenericParamTableEntry, 1);
2205 entry->owner = owner;
2206 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2207 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2208 entry->gparam = gparam;
2210 g_ptr_array_add (assembly->gen_params, entry);
2214 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2216 MonoDynamicTable *table;
2217 MonoGenericParam *param;
2221 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2222 table_idx = table->next_idx ++;
2223 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2225 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2227 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2228 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2229 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2230 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2232 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2234 encode_constraints (entry->gparam, table_idx, assembly);
2238 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2240 MonoDynamicTable *table;
2243 guint32 cols [MONO_ASSEMBLY_SIZE];
2247 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2250 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2251 table = &assembly->tables [MONO_TABLE_MODULEREF];
2252 token = table->next_idx ++;
2254 alloc_table (table, table->rows);
2255 values = table->values + token * MONO_MODULEREF_SIZE;
2256 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2258 token <<= MONO_RESOLTION_SCOPE_BITS;
2259 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2260 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2265 if (image->assembly->dynamic)
2267 memset (cols, 0, sizeof (cols));
2269 /* image->assembly->image is the manifest module */
2270 image = image->assembly->image;
2271 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2274 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2275 token = table->next_idx ++;
2277 alloc_table (table, table->rows);
2278 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2279 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2280 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2281 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2282 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2283 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2284 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2285 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2286 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2288 if (strcmp ("", image->assembly->aname.culture)) {
2289 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2290 image->assembly->aname.culture);
2293 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2294 guchar pubtoken [9];
2296 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2297 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2299 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2301 token <<= MONO_RESOLTION_SCOPE_BITS;
2302 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2303 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2308 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2310 MonoDynamicTable *table;
2315 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2318 sigbuffer_init (&buf, 32);
2319 switch (type->type) {
2320 case MONO_TYPE_FNPTR:
2322 case MONO_TYPE_SZARRAY:
2323 case MONO_TYPE_ARRAY:
2325 case MONO_TYPE_MVAR:
2326 case MONO_TYPE_GENERICINST:
2327 encode_type (assembly, type, &buf);
2329 case MONO_TYPE_CLASS:
2330 case MONO_TYPE_VALUETYPE: {
2331 MonoClass *k = mono_class_from_mono_type (type);
2332 if (!k || !k->generic_container) {
2333 sigbuffer_free (&buf);
2336 encode_type (assembly, type, &buf);
2340 sigbuffer_free (&buf);
2344 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2345 if (assembly->save) {
2346 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2347 alloc_table (table, table->rows + 1);
2348 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2349 values [MONO_TYPESPEC_SIGNATURE] = token;
2351 sigbuffer_free (&buf);
2353 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2354 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2360 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2362 MonoDynamicTable *table;
2364 guint32 token, scope, enclosing;
2367 /* if the type requires a typespec, we must try that first*/
2368 if (try_typespec && (token = create_typespec (assembly, type)))
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2373 klass = mono_class_from_mono_type (type);
2375 klass = mono_class_from_mono_type (type);
2378 * If it's in the same module and not a generic type parameter:
2380 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2381 (type->type != MONO_TYPE_MVAR)) {
2382 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2383 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2384 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2388 if (klass->nested_in) {
2389 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2390 /* get the typeref idx of the enclosing type */
2391 enclosing >>= MONO_TYPEDEFORREF_BITS;
2392 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2394 scope = resolution_scope_from_image (assembly, klass->image);
2396 table = &assembly->tables [MONO_TABLE_TYPEREF];
2397 if (assembly->save) {
2398 alloc_table (table, table->rows + 1);
2399 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2400 values [MONO_TYPEREF_SCOPE] = scope;
2401 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2402 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2404 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2405 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2407 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2412 * Despite the name, we handle also TypeSpec (with the above helper).
2415 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2417 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2420 #ifndef DISABLE_REFLECTION_EMIT
2422 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2424 MonoDynamicTable *table;
2426 guint32 token, pclass;
2428 switch (parent & MONO_TYPEDEFORREF_MASK) {
2429 case MONO_TYPEDEFORREF_TYPEREF:
2430 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2432 case MONO_TYPEDEFORREF_TYPESPEC:
2433 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2435 case MONO_TYPEDEFORREF_TYPEDEF:
2436 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2439 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2442 /* extract the index */
2443 parent >>= MONO_TYPEDEFORREF_BITS;
2445 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2447 if (assembly->save) {
2448 alloc_table (table, table->rows + 1);
2449 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2450 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2451 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2452 values [MONO_MEMBERREF_SIGNATURE] = sig;
2455 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2462 * Insert a memberef row into the metadata: the token that point to the memberref
2463 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2464 * mono_image_get_fieldref_token()).
2465 * The sig param is an index to an already built signature.
2468 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2470 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2471 return mono_image_add_memberef_row (assembly, parent, name, sig);
2476 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2479 MonoMethodSignature *sig;
2481 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2483 if (create_typespec) {
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2489 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2490 if (token && !create_typespec)
2493 g_assert (!method->is_inflated);
2496 * A methodref signature can't contain an unmanaged calling convention.
2498 sig = mono_metadata_signature_dup (mono_method_signature (method));
2499 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2500 sig->call_convention = MONO_CALL_DEFAULT;
2501 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2502 method->name, method_encode_signature (assembly, sig));
2504 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2507 if (create_typespec) {
2508 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2509 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2510 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2512 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517 values [MONO_METHODSPEC_METHOD] = token;
2518 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2521 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2523 /*methodspec and memberef tokens are diferent, */
2524 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2531 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2533 guint32 token, parent, sig;
2534 ReflectionMethodBuilder rmb;
2536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2538 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2542 name = mono_string_to_utf8 (method->name);
2543 reflection_methodbuilder_from_method_builder (&rmb, method);
2546 * A methodref signature can't contain an unmanaged calling convention.
2547 * Since some flags are encoded as part of call_conv, we need to check against it.
2549 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2550 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2552 sig = method_builder_encode_signature (assembly, &rmb);
2554 if (tb->generic_params)
2555 parent = create_generic_typespec (assembly, tb);
2557 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2559 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2562 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2567 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2568 const gchar *name, guint32 sig)
2570 MonoDynamicTable *table;
2574 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2576 if (assembly->save) {
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2579 values [MONO_MEMBERREF_CLASS] = original;
2580 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2581 values [MONO_MEMBERREF_SIGNATURE] = sig;
2584 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2591 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2595 guint32 nparams = mono_array_length (mb->generic_params);
2598 if (!assembly->save)
2601 sigbuffer_init (&buf, 32);
2603 sigbuffer_add_value (&buf, 0xa);
2604 sigbuffer_add_value (&buf, nparams);
2606 for (i = 0; i < nparams; i++) {
2607 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2608 sigbuffer_add_value (&buf, i);
2611 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2612 sigbuffer_free (&buf);
2617 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2619 MonoDynamicTable *table;
2621 guint32 token, mtoken = 0;
2623 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2627 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2629 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2630 switch (mono_metadata_token_table (mtoken)) {
2631 case MONO_TABLE_MEMBERREF:
2632 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2634 case MONO_TABLE_METHOD:
2635 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2638 g_assert_not_reached ();
2641 if (assembly->save) {
2642 alloc_table (table, table->rows + 1);
2643 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2644 values [MONO_METHODSPEC_METHOD] = mtoken;
2645 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2648 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2651 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2656 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2660 if (mb->generic_params && create_methodspec)
2661 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2663 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2667 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2668 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2673 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2675 guint32 token, parent, sig;
2676 ReflectionMethodBuilder rmb;
2678 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2680 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2684 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2686 if (tb->generic_params)
2687 parent = create_generic_typespec (assembly, tb);
2689 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2691 name = mono_string_to_utf8 (rmb.name);
2692 sig = method_builder_encode_signature (assembly, &rmb);
2694 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2697 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2703 is_field_on_inst (MonoClassField *field)
2705 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2709 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2712 get_field_on_inst_generic_type (MonoClassField *field)
2714 MonoClass *class, *gtd;
2715 MonoDynamicGenericClass *dgclass;
2718 g_assert (is_field_on_inst (field));
2720 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2722 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2723 field_index = field - dgclass->fields;
2724 return dgclass->field_generic_types [field_index];
2727 class = field->parent;
2728 gtd = class->generic_class->container_class;
2730 if (field >= class->fields && field - class->fields < class->field.count) {
2731 field_index = field - class->fields;
2732 return gtd->fields [field_index].type;
2735 g_assert_not_reached ();
2739 #ifndef DISABLE_REFLECTION_EMIT
2741 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2747 g_assert (field->parent);
2749 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2753 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2754 int index = field - field->parent->fields;
2755 type = field->parent->generic_class->container_class->fields [index].type;
2757 if (is_field_on_inst (field))
2758 type = get_field_on_inst_generic_type (field);
2760 type = mono_field_get_type (field);
2762 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2763 mono_field_get_name (field),
2764 fieldref_encode_signature (assembly, field->parent->image, type));
2765 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2770 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2774 MonoGenericClass *gclass;
2775 MonoDynamicGenericClass *dgclass;
2779 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2782 if (is_sre_field_builder (mono_object_class (f->fb))) {
2783 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2784 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785 klass = mono_class_from_mono_type (type);
2786 gclass = type->data.generic_class;
2787 g_assert (gclass->is_dynamic);
2788 dgclass = (MonoDynamicGenericClass *) gclass;
2790 name = mono_string_to_utf8 (fb->name);
2791 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2792 field_encode_signature (assembly, fb));
2794 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2796 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2798 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2799 klass = mono_class_from_mono_type (type);
2801 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2802 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2804 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2805 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2808 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2813 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2817 MonoGenericClass *gclass;
2820 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2822 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2826 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2827 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2828 MonoDynamicGenericClass *dgclass;
2829 ReflectionMethodBuilder rmb;
2832 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2833 klass = mono_class_from_mono_type (type);
2835 gclass = type->data.generic_class;
2836 g_assert (gclass->is_dynamic);
2837 dgclass = (MonoDynamicGenericClass *) gclass;
2839 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2841 name = mono_string_to_utf8 (rmb.name);
2843 sig = method_builder_encode_signature (assembly, &rmb);
2845 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2847 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2848 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2850 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2851 klass = mono_class_from_mono_type (type);
2853 sig = method_encode_signature (assembly, mono_method_signature (mm));
2854 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2856 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2857 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2861 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2866 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2869 MonoGenericContext tmp_context;
2870 MonoType **type_argv;
2871 MonoGenericInst *ginst;
2872 MonoMethod *method, *inflated;
2875 init_type_builder_generics ((MonoObject*)m->inst);
2877 method = inflate_method (m->inst, (MonoObject*)m->mb);
2879 klass = method->klass;
2881 if (m->method_args == NULL)
2884 if (method->is_inflated)
2885 method = ((MonoMethodInflated *) method)->declaring;
2887 count = mono_array_length (m->method_args);
2889 type_argv = g_new0 (MonoType *, count);
2890 for (i = 0; i < count; i++) {
2891 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2892 type_argv [i] = mono_reflection_type_get_handle (garg);
2894 ginst = mono_metadata_get_generic_inst (count, type_argv);
2897 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2898 tmp_context.method_inst = ginst;
2900 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2905 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2907 guint32 sig, token = 0;
2911 if (m->method_args) {
2912 MonoMethod *inflated;
2914 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2915 if (create_methodspec)
2916 token = mono_image_get_methodspec_token (assembly, inflated);
2918 token = mono_image_get_inflated_method_token (assembly, inflated);
2922 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2926 if (is_sre_method_builder (mono_object_class (m->mb))) {
2927 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2928 MonoGenericClass *gclass;
2929 ReflectionMethodBuilder rmb;
2932 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2933 klass = mono_class_from_mono_type (type);
2934 gclass = type->data.generic_class;
2935 g_assert (gclass->is_dynamic);
2937 reflection_methodbuilder_from_method_builder (&rmb, mb);
2939 name = mono_string_to_utf8 (rmb.name);
2941 sig = method_builder_encode_signature (assembly, &rmb);
2943 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2945 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2946 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2948 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2949 klass = mono_class_from_mono_type (type);
2951 sig = method_encode_signature (assembly, mono_method_signature (mm));
2952 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2954 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2955 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2958 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2963 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2967 guint32 nparams = context->method_inst->type_argc;
2970 if (!assembly->save)
2973 sigbuffer_init (&buf, 32);
2975 * FIXME: vararg, explicit_this, differenc call_conv values...
2977 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2978 sigbuffer_add_value (&buf, nparams);
2980 for (i = 0; i < nparams; i++)
2981 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2983 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2984 sigbuffer_free (&buf);
2989 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2991 MonoDynamicTable *table;
2993 guint32 token, mtoken = 0, sig;
2994 MonoMethodInflated *imethod;
2995 MonoMethod *declaring;
2997 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2999 g_assert (method->is_inflated);
3000 imethod = (MonoMethodInflated *) method;
3001 declaring = imethod->declaring;
3003 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3004 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3006 if (!mono_method_signature (declaring)->generic_param_count)
3009 switch (mono_metadata_token_table (mtoken)) {
3010 case MONO_TABLE_MEMBERREF:
3011 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3013 case MONO_TABLE_METHOD:
3014 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3017 g_assert_not_reached ();
3020 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3022 if (assembly->save) {
3023 alloc_table (table, table->rows + 1);
3024 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3025 values [MONO_METHODSPEC_METHOD] = mtoken;
3026 values [MONO_METHODSPEC_SIGNATURE] = sig;
3029 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3036 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3038 MonoMethodInflated *imethod;
3041 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3045 g_assert (method->is_inflated);
3046 imethod = (MonoMethodInflated *) method;
3048 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3049 token = method_encode_methodspec (assembly, method);
3051 guint32 sig = method_encode_signature (
3052 assembly, mono_method_signature (imethod->declaring));
3053 token = mono_image_get_memberref_token (
3054 assembly, &method->klass->byval_arg, method->name, sig);
3057 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3062 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3064 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3067 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3068 token = mono_image_get_memberref_token (
3069 assembly, &m->klass->byval_arg, m->name, sig);
3075 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3077 MonoDynamicTable *table;
3086 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3087 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3088 * Because of this, we must not insert it into the `typeref' hash table.
3090 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3091 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3095 sigbuffer_init (&buf, 32);
3097 g_assert (tb->generic_params);
3098 klass = mono_class_from_mono_type (type);
3100 if (tb->generic_container)
3101 mono_reflection_create_generic_class (tb);
3103 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3104 g_assert (klass->generic_container);
3105 sigbuffer_add_value (&buf, klass->byval_arg.type);
3106 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3108 count = mono_array_length (tb->generic_params);
3109 sigbuffer_add_value (&buf, count);
3110 for (i = 0; i < count; i++) {
3111 MonoReflectionGenericParam *gparam;
3113 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3115 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3118 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3120 if (assembly->save) {
3121 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3122 alloc_table (table, table->rows + 1);
3123 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3124 values [MONO_TYPESPEC_SIGNATURE] = token;
3126 sigbuffer_free (&buf);
3128 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3129 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3135 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3138 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3140 int i, count, len, pos;
3145 count += mono_array_length (modreq);
3147 count += mono_array_length (modopt);
3150 return mono_metadata_type_dup (NULL, type);
3152 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3154 memcpy (t, type, MONO_SIZEOF_TYPE);
3156 t->num_mods = count;
3159 for (i = 0; i < mono_array_length (modreq); ++i) {
3160 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3161 t->modifiers [pos].required = 1;
3162 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3167 for (i = 0; i < mono_array_length (modopt); ++i) {
3168 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3169 t->modifiers [pos].required = 0;
3170 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3179 init_type_builder_generics (MonoObject *type)
3181 MonoReflectionTypeBuilder *tb;
3183 if (!is_sre_type_builder(mono_object_class (type)))
3185 tb = (MonoReflectionTypeBuilder *)type;
3187 if (tb && tb->generic_container)
3188 mono_reflection_create_generic_class (tb);
3192 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3194 MonoDynamicTable *table;
3196 MonoType *custom = NULL, *type;
3198 guint32 token, pclass, parent, sig;
3201 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3205 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3206 name = mono_string_to_utf8 (fb->name);
3208 /*FIXME this is one more layer of ugliness due how types are created.*/
3209 init_type_builder_generics (fb->type);
3211 /* fb->type does not include the custom modifiers */
3212 /* FIXME: We should do this in one place when a fieldbuilder is created */
3213 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3214 if (fb->modreq || fb->modopt)
3215 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3217 sig = fieldref_encode_signature (assembly, NULL, type);
3220 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3221 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3223 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3224 parent >>= MONO_TYPEDEFORREF_BITS;
3226 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3228 if (assembly->save) {
3229 alloc_table (table, table->rows + 1);
3230 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3231 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3232 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3233 values [MONO_MEMBERREF_SIGNATURE] = sig;
3236 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3238 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3244 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3251 if (!assembly->save)
3254 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3255 g_assert (helper->type == 2);
3257 if (helper->arguments)
3258 nargs = mono_array_length (helper->arguments);
3262 size = 10 + (nargs * 10);
3264 sigbuffer_init (&buf, 32);
3266 /* Encode calling convention */
3267 /* Change Any to Standard */
3268 if ((helper->call_conv & 0x03) == 0x03)
3269 helper->call_conv = 0x01;
3270 /* explicit_this implies has_this */
3271 if (helper->call_conv & 0x40)
3272 helper->call_conv &= 0x20;
3274 if (helper->call_conv == 0) { /* Unmanaged */
3275 idx = helper->unmanaged_call_conv - 1;
3278 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3279 if (helper->call_conv & 0x02) /* varargs */
3283 sigbuffer_add_byte (&buf, idx);
3284 sigbuffer_add_value (&buf, nargs);
3285 encode_reflection_type (assembly, helper->return_type, &buf);
3286 for (i = 0; i < nargs; ++i) {
3287 MonoArray *modreqs = NULL;
3288 MonoArray *modopts = NULL;
3289 MonoReflectionType *pt;
3291 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3292 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3293 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3294 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3296 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3297 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3298 encode_reflection_type (assembly, pt, &buf);
3300 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3301 sigbuffer_free (&buf);
3307 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3310 MonoDynamicTable *table;
3313 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3314 idx = table->next_idx ++;
3316 alloc_table (table, table->rows);
3317 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3319 values [MONO_STAND_ALONE_SIGNATURE] =
3320 mono_reflection_encode_sighelper (assembly, helper);
3326 reflection_cc_to_file (int call_conv) {
3327 switch (call_conv & 0x3) {
3329 case 1: return MONO_CALL_DEFAULT;
3330 case 2: return MONO_CALL_VARARG;
3332 g_assert_not_reached ();
3336 #endif /* !DISABLE_REFLECTION_EMIT */
3340 MonoMethodSignature *sig;
3345 #ifndef DISABLE_REFLECTION_EMIT
3347 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3352 MonoMethodSignature *sig;
3356 name = mono_string_to_utf8 (m->name);
3357 nparams = mono_array_length (m->parameters);
3358 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3360 sig->sentinelpos = -1;
3361 sig->call_convention = reflection_cc_to_file (m->call_conv);
3362 sig->param_count = nparams;
3363 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3364 mtype = mono_reflection_type_get_handle (m->parent);
3365 for (i = 0; i < nparams; ++i)
3366 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3368 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3370 if (strcmp (name, am->name) == 0 &&
3371 mono_metadata_type_equal (am->parent, mtype) &&
3372 mono_metadata_signature_equal (am->sig, sig)) {
3375 m->table_idx = am->token & 0xffffff;
3379 am = g_new0 (ArrayMethod, 1);
3383 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3384 method_encode_signature (assembly, sig));
3385 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3386 m->table_idx = am->token & 0xffffff;
3391 * Insert into the metadata tables all the info about the TypeBuilder tb.
3392 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3395 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3397 MonoDynamicTable *table;
3399 int i, is_object = 0, is_system = 0;
3402 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3403 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3404 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3405 n = mono_string_to_utf8 (tb->name);
3406 if (strcmp (n, "Object") == 0)
3408 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3410 n = mono_string_to_utf8 (tb->nspace);
3411 if (strcmp (n, "System") == 0)
3413 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3415 if (tb->parent && !(is_system && is_object) &&
3416 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3417 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3419 values [MONO_TYPEDEF_EXTENDS] = 0;
3421 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3422 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3425 * if we have explicitlayout or sequentiallayouts, output data in the
3426 * ClassLayout table.
3428 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3429 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3430 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3432 alloc_table (table, table->rows);
3433 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3434 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3435 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3436 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3439 /* handle interfaces */
3440 if (tb->interfaces) {
3441 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3443 table->rows += mono_array_length (tb->interfaces);
3444 alloc_table (table, table->rows);
3445 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3446 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3447 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3448 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3449 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3450 values += MONO_INTERFACEIMPL_SIZE;
3456 table = &assembly->tables [MONO_TABLE_FIELD];
3457 table->rows += tb->num_fields;
3458 alloc_table (table, table->rows);
3459 for (i = 0; i < tb->num_fields; ++i)
3460 mono_image_get_field_info (
3461 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3464 /* handle constructors */
3466 table = &assembly->tables [MONO_TABLE_METHOD];
3467 table->rows += mono_array_length (tb->ctors);
3468 alloc_table (table, table->rows);
3469 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3470 mono_image_get_ctor_info (domain,
3471 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3474 /* handle methods */
3476 table = &assembly->tables [MONO_TABLE_METHOD];
3477 table->rows += tb->num_methods;
3478 alloc_table (table, table->rows);
3479 for (i = 0; i < tb->num_methods; ++i)
3480 mono_image_get_method_info (
3481 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3484 /* Do the same with properties etc.. */
3485 if (tb->events && mono_array_length (tb->events)) {
3486 table = &assembly->tables [MONO_TABLE_EVENT];
3487 table->rows += mono_array_length (tb->events);
3488 alloc_table (table, table->rows);
3489 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3491 alloc_table (table, table->rows);
3492 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3493 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3494 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3495 for (i = 0; i < mono_array_length (tb->events); ++i)
3496 mono_image_get_event_info (
3497 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3499 if (tb->properties && mono_array_length (tb->properties)) {
3500 table = &assembly->tables [MONO_TABLE_PROPERTY];
3501 table->rows += mono_array_length (tb->properties);
3502 alloc_table (table, table->rows);
3503 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3505 alloc_table (table, table->rows);
3506 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3507 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3508 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3509 for (i = 0; i < mono_array_length (tb->properties); ++i)
3510 mono_image_get_property_info (
3511 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3514 /* handle generic parameters */
3515 if (tb->generic_params) {
3516 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3517 table->rows += mono_array_length (tb->generic_params);
3518 alloc_table (table, table->rows);
3519 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3520 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3522 mono_image_get_generic_param_info (
3523 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3527 mono_image_add_decl_security (assembly,
3528 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3531 MonoDynamicTable *ntable;
3533 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3534 ntable->rows += mono_array_length (tb->subtypes);
3535 alloc_table (ntable, ntable->rows);
3536 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3538 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3539 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3541 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3542 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3543 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3544 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3545 mono_string_to_utf8 (tb->name), tb->table_idx,
3546 ntable->next_idx, ntable->rows);*/
3547 values += MONO_NESTED_CLASS_SIZE;
3555 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3559 mono_ptr_array_append (*types, type);
3561 if (!type->subtypes)
3564 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3565 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3566 collect_types (types, subtype);
3571 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3573 if ((*type1)->table_idx < (*type2)->table_idx)
3576 if ((*type1)->table_idx > (*type2)->table_idx)
3583 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3588 for (i = 0; i < mono_array_length (pinfo); ++i) {
3589 MonoReflectionParamBuilder *pb;
3590 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3593 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3598 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3601 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3603 for (i = 0; i < tb->num_fields; ++i) {
3604 MonoReflectionFieldBuilder* fb;
3605 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3606 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3610 for (i = 0; i < mono_array_length (tb->events); ++i) {
3611 MonoReflectionEventBuilder* eb;
3612 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3613 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3616 if (tb->properties) {
3617 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3618 MonoReflectionPropertyBuilder* pb;
3619 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3620 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3624 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3625 MonoReflectionCtorBuilder* cb;
3626 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3627 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3628 params_add_cattrs (assembly, cb->pinfo);
3633 for (i = 0; i < tb->num_methods; ++i) {
3634 MonoReflectionMethodBuilder* mb;
3635 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3636 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3637 params_add_cattrs (assembly, mb->pinfo);
3642 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3643 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3648 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3652 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3654 if (moduleb->global_methods) {
3655 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3656 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3657 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3658 params_add_cattrs (assembly, mb->pinfo);
3662 if (moduleb->global_fields) {
3663 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3664 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3665 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3669 if (moduleb->types) {
3670 for (i = 0; i < moduleb->num_types; ++i)
3671 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3676 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3678 MonoDynamicTable *table;
3682 char *b = blob_size;
3685 table = &assembly->tables [MONO_TABLE_FILE];
3687 alloc_table (table, table->rows);
3688 values = table->values + table->next_idx * MONO_FILE_SIZE;
3689 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3690 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3691 if (module->image->dynamic) {
3692 /* This depends on the fact that the main module is emitted last */
3693 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3694 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3697 path = g_strdup (module->image->name);
3699 mono_sha1_get_digest_from_file (path, hash);
3702 mono_metadata_encode_value (20, b, &b);
3703 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3704 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3709 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3711 MonoDynamicTable *table;
3714 table = &assembly->tables [MONO_TABLE_MODULE];
3715 mb->table_idx = table->next_idx ++;
3716 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3717 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3720 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3721 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3722 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3723 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3727 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3728 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3730 MonoDynamicTable *table;
3734 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3735 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3738 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3740 alloc_table (table, table->rows);
3741 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3743 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3744 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3745 if (klass->nested_in)
3746 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3748 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3749 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3750 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3752 res = table->next_idx;
3756 /* Emit nested types */
3757 if (klass->ext && klass->ext->nested_classes) {
3760 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3761 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3768 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3769 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3774 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3776 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3778 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3779 parent_index, assembly);
3783 * We need to do this ourselves since klass->nested_classes is not set up.
3786 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3787 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3792 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3793 guint32 module_index, MonoDynamicImage *assembly)
3795 MonoImage *image = module->image;
3799 t = &image->tables [MONO_TABLE_TYPEDEF];
3801 for (i = 0; i < t->rows; ++i) {
3802 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3804 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3805 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3810 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3812 MonoDynamicTable *table;
3814 guint32 scope, scope_idx, impl, current_idx;
3815 gboolean forwarder = TRUE;
3816 gpointer iter = NULL;
3819 if (klass->nested_in) {
3820 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3823 scope = resolution_scope_from_image (assembly, klass->image);
3824 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3825 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3826 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3829 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3832 alloc_table (table, table->rows);
3833 current_idx = table->next_idx;
3834 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3836 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3837 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3838 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3839 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3840 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3844 while ((nested = mono_class_get_nested_types (klass, &iter)))
3845 add_exported_type (assemblyb, assembly, nested, current_idx);
3849 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3854 if (!assemblyb->type_forwarders)
3857 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3858 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3863 type = mono_reflection_type_get_handle (t);
3866 klass = mono_class_from_mono_type (type);
3868 add_exported_type (assemblyb, assembly, klass, 0);
3872 #define align_pointer(base,p)\
3874 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3876 (p) += 4 - (__diff & 3);\
3880 compare_constants (const void *a, const void *b)
3882 const guint32 *a_values = a;
3883 const guint32 *b_values = b;
3884 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3888 compare_semantics (const void *a, const void *b)
3890 const guint32 *a_values = a;
3891 const guint32 *b_values = b;
3892 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3895 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3899 compare_custom_attrs (const void *a, const void *b)
3901 const guint32 *a_values = a;
3902 const guint32 *b_values = b;
3904 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3908 compare_field_marshal (const void *a, const void *b)
3910 const guint32 *a_values = a;
3911 const guint32 *b_values = b;
3913 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3917 compare_nested (const void *a, const void *b)
3919 const guint32 *a_values = a;
3920 const guint32 *b_values = b;
3922 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3926 compare_genericparam (const void *a, const void *b)
3928 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3929 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3931 if ((*b_entry)->owner == (*a_entry)->owner)
3933 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3934 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3936 return (*a_entry)->owner - (*b_entry)->owner;
3940 compare_declsecurity_attrs (const void *a, const void *b)
3942 const guint32 *a_values = a;
3943 const guint32 *b_values = b;
3945 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3949 compare_interface_impl (const void *a, const void *b)
3951 const guint32 *a_values = a;
3952 const guint32 *b_values = b;
3954 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3958 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3962 pad_heap (MonoDynamicStream *sh)
3964 if (sh->index & 3) {
3965 int sz = 4 - (sh->index & 3);
3966 memset (sh->data + sh->index, 0, sz);
3973 MonoDynamicStream *stream;
3977 * build_compressed_metadata() fills in the blob of data that represents the
3978 * raw metadata as it will be saved in the PE file. The five streams are output
3979 * and the metadata tables are comnpressed from the guint32 array representation,
3980 * to the compressed on-disk format.
3983 build_compressed_metadata (MonoDynamicImage *assembly)
3985 MonoDynamicTable *table;
3987 guint64 valid_mask = 0;
3988 guint64 sorted_mask;
3989 guint32 heapt_size = 0;
3990 guint32 meta_size = 256; /* allow for header and other stuff */
3991 guint32 table_offset;
3992 guint32 ntables = 0;
3998 struct StreamDesc stream_desc [5];
4000 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4001 for (i = 0; i < assembly->gen_params->len; i++){
4002 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4003 write_generic_param_entry (assembly, entry);
4006 stream_desc [0].name = "#~";
4007 stream_desc [0].stream = &assembly->tstream;
4008 stream_desc [1].name = "#Strings";
4009 stream_desc [1].stream = &assembly->sheap;
4010 stream_desc [2].name = "#US";
4011 stream_desc [2].stream = &assembly->us;
4012 stream_desc [3].name = "#Blob";
4013 stream_desc [3].stream = &assembly->blob;
4014 stream_desc [4].name = "#GUID";
4015 stream_desc [4].stream = &assembly->guid;
4017 /* tables that are sorted */
4018 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4019 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4020 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4021 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4022 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4023 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4024 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4026 /* Compute table sizes */
4027 /* the MonoImage has already been created in mono_image_basic_init() */
4028 meta = &assembly->image;
4030 /* sizes should be multiple of 4 */
4031 pad_heap (&assembly->blob);
4032 pad_heap (&assembly->guid);
4033 pad_heap (&assembly->sheap);
4034 pad_heap (&assembly->us);
4036 /* Setup the info used by compute_sizes () */
4037 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4038 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4039 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4041 meta_size += assembly->blob.index;
4042 meta_size += assembly->guid.index;
4043 meta_size += assembly->sheap.index;
4044 meta_size += assembly->us.index;
4046 for (i=0; i < MONO_TABLE_NUM; ++i)
4047 meta->tables [i].rows = assembly->tables [i].rows;
4049 for (i = 0; i < MONO_TABLE_NUM; i++){
4050 if (meta->tables [i].rows == 0)
4052 valid_mask |= (guint64)1 << i;
4054 meta->tables [i].row_size = mono_metadata_compute_size (
4055 meta, i, &meta->tables [i].size_bitfield);
4056 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4058 heapt_size += 24; /* #~ header size */
4059 heapt_size += ntables * 4;
4060 /* make multiple of 4 */
4063 meta_size += heapt_size;
4064 meta->raw_metadata = g_malloc0 (meta_size);
4065 p = (unsigned char*)meta->raw_metadata;
4066 /* the metadata signature */
4067 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4068 /* version numbers and 4 bytes reserved */
4069 int16val = (guint16*)p;
4070 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4071 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4073 /* version string */
4074 int32val = (guint32*)p;
4075 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4077 memcpy (p, meta->version, strlen (meta->version));
4078 p += GUINT32_FROM_LE (*int32val);
4079 align_pointer (meta->raw_metadata, p);
4080 int16val = (guint16*)p;
4081 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4082 *int16val = GUINT16_TO_LE (5); /* number of streams */
4086 * write the stream info.
4088 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4089 table_offset += 3; table_offset &= ~3;
4091 assembly->tstream.index = heapt_size;
4092 for (i = 0; i < 5; ++i) {
4093 int32val = (guint32*)p;
4094 stream_desc [i].stream->offset = table_offset;
4095 *int32val++ = GUINT32_TO_LE (table_offset);
4096 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4097 table_offset += GUINT32_FROM_LE (*int32val);
4098 table_offset += 3; table_offset &= ~3;
4100 strcpy ((char*)p, stream_desc [i].name);
4101 p += strlen (stream_desc [i].name) + 1;
4102 align_pointer (meta->raw_metadata, p);
4105 * now copy the data, the table stream header and contents goes first.
4107 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4108 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4109 int32val = (guint32*)p;
4110 *int32val = GUINT32_TO_LE (0); /* reserved */
4113 *p++ = 2; /* version */
4116 if (meta->idx_string_wide)
4118 if (meta->idx_guid_wide)
4120 if (meta->idx_blob_wide)
4123 *p++ = 1; /* reserved */
4124 int64val = (guint64*)p;
4125 *int64val++ = GUINT64_TO_LE (valid_mask);
4126 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4128 int32val = (guint32*)p;
4129 for (i = 0; i < MONO_TABLE_NUM; i++){
4130 if (meta->tables [i].rows == 0)
4132 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4134 p = (unsigned char*)int32val;
4136 /* sort the tables that still need sorting */
4137 table = &assembly->tables [MONO_TABLE_CONSTANT];
4139 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4140 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4142 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4143 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4145 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4146 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4148 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4149 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4151 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4152 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4153 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4155 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4156 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4158 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4160 /* compress the tables */
4161 for (i = 0; i < MONO_TABLE_NUM; i++){
4164 guint32 bitfield = meta->tables [i].size_bitfield;
4165 if (!meta->tables [i].rows)
4167 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4168 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4169 meta->tables [i].base = (char*)p;
4170 for (row = 1; row <= meta->tables [i].rows; ++row) {
4171 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4172 for (col = 0; col < assembly->tables [i].columns; ++col) {
4173 switch (mono_metadata_table_size (bitfield, col)) {
4175 *p++ = values [col];
4178 *p++ = values [col] & 0xff;
4179 *p++ = (values [col] >> 8) & 0xff;
4182 *p++ = values [col] & 0xff;
4183 *p++ = (values [col] >> 8) & 0xff;
4184 *p++ = (values [col] >> 16) & 0xff;
4185 *p++ = (values [col] >> 24) & 0xff;
4188 g_assert_not_reached ();
4192 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4195 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4196 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4197 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4198 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4199 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4201 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4205 * Some tables in metadata need to be sorted according to some criteria, but
4206 * when methods and fields are first created with reflection, they may be assigned a token
4207 * that doesn't correspond to the final token they will get assigned after the sorting.
4208 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4209 * with the reflection objects that represent them. Once all the tables are set up, the
4210 * reflection objects will contains the correct table index. fixup_method() will fixup the
4211 * tokens for the method with ILGenerator @ilgen.
4214 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4216 guint32 code_idx = GPOINTER_TO_UINT (value);
4217 MonoReflectionILTokenInfo *iltoken;
4218 MonoReflectionFieldBuilder *field;
4219 MonoReflectionCtorBuilder *ctor;
4220 MonoReflectionMethodBuilder *method;
4221 MonoReflectionTypeBuilder *tb;
4222 MonoReflectionArrayMethod *am;
4224 unsigned char *target;
4226 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4227 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4228 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4229 switch (target [3]) {
4230 case MONO_TABLE_FIELD:
4231 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4232 field = (MonoReflectionFieldBuilder *)iltoken->member;
4233 idx = field->table_idx;
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4235 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4236 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4238 g_assert_not_reached ();
4241 case MONO_TABLE_METHOD:
4242 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4243 method = (MonoReflectionMethodBuilder *)iltoken->member;
4244 idx = method->table_idx;
4245 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4246 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4247 idx = ctor->table_idx;
4248 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4249 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4250 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4251 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4253 g_assert_not_reached ();
4256 case MONO_TABLE_TYPEDEF:
4257 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4258 g_assert_not_reached ();
4259 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4260 idx = tb->table_idx;
4262 case MONO_TABLE_MEMBERREF:
4263 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4264 am = (MonoReflectionArrayMethod*)iltoken->member;
4265 idx = am->table_idx;
4266 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4267 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4268 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4269 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4270 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4271 g_assert (m->klass->generic_class || m->klass->generic_container);
4273 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4275 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4276 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4277 g_assert (is_field_on_inst (f));
4279 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4280 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4282 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4284 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4286 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4289 g_assert_not_reached ();
4292 case MONO_TABLE_METHODSPEC:
4293 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4294 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4295 g_assert (mono_method_signature (m)->generic_param_count);
4297 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4299 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4302 g_assert_not_reached ();
4306 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4308 target [0] = idx & 0xff;
4309 target [1] = (idx >> 8) & 0xff;
4310 target [2] = (idx >> 16) & 0xff;
4317 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4318 * value is not known when the table is emitted.
4321 fixup_cattrs (MonoDynamicImage *assembly)
4323 MonoDynamicTable *table;
4325 guint32 type, i, idx, token;
4328 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4330 for (i = 0; i < table->rows; ++i) {
4331 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4333 type = values [MONO_CUSTOM_ATTR_TYPE];
4334 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4335 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4336 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4337 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4340 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4341 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4342 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4343 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4344 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4345 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4346 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4347 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4354 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4356 MonoDynamicTable *table;
4359 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4361 alloc_table (table, table->rows);
4362 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4363 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4364 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4365 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4366 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4371 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4373 MonoDynamicTable *table;
4377 char *b = blob_size;
4379 guint32 idx, offset;
4381 if (rsrc->filename) {
4382 name = mono_string_to_utf8 (rsrc->filename);
4383 sname = g_path_get_basename (name);
4385 table = &assembly->tables [MONO_TABLE_FILE];
4387 alloc_table (table, table->rows);
4388 values = table->values + table->next_idx * MONO_FILE_SIZE;
4389 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4390 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4393 mono_sha1_get_digest_from_file (name, hash);
4394 mono_metadata_encode_value (20, b, &b);
4395 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4396 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4398 idx = table->next_idx++;
4400 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4406 data = mono_array_addr (rsrc->data, char, 0);
4407 len = mono_array_length (rsrc->data);
4413 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4414 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4415 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4416 mono_image_add_stream_data (&assembly->resources, data, len);
4420 * The entry should be emitted into the MANIFESTRESOURCE table of
4421 * the main module, but that needs to reference the FILE table
4422 * which isn't emitted yet.
4429 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4433 set_version_from_string (MonoString *version, guint32 *values)
4435 gchar *ver, *p, *str;
4438 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4439 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4440 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4441 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4444 ver = str = mono_string_to_utf8 (version);
4445 for (i = 0; i < 4; ++i) {
4446 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4452 /* handle Revision and Build */
4462 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4466 char *b = blob_size;
4471 len = mono_array_length (pkey);
4472 mono_metadata_encode_value (len, b, &b);
4473 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4474 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4476 assembly->public_key = g_malloc (len);
4477 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4478 assembly->public_key_len = len;
4480 /* Special case: check for ECMA key (16 bytes) */
4481 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4482 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4483 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4484 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4485 /* minimum key size (in 2.0) is 384 bits */
4486 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4488 /* FIXME - verifier */
4489 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4490 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4492 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4498 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4500 MonoDynamicTable *table;
4501 MonoDynamicImage *assembly;
4502 MonoReflectionAssemblyBuilder *assemblyb;
4506 guint32 module_index;
4508 assemblyb = moduleb->assemblyb;
4509 assembly = moduleb->dynamic_image;
4510 domain = mono_object_domain (assemblyb);
4512 /* Emit ASSEMBLY table */
4513 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4514 alloc_table (table, 1);
4515 values = table->values + MONO_ASSEMBLY_SIZE;
4516 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4517 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4518 if (assemblyb->culture) {
4519 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4521 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4523 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4524 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4525 set_version_from_string (assemblyb->version, values);
4527 /* Emit FILE + EXPORTED_TYPE table */
4529 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4531 MonoReflectionModuleBuilder *file_module =
4532 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4533 if (file_module != moduleb) {
4534 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4536 if (file_module->types) {
4537 for (j = 0; j < file_module->num_types; ++j) {
4538 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4539 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4544 if (assemblyb->loaded_modules) {
4545 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4546 MonoReflectionModule *file_module =
4547 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4548 mono_image_fill_file_table (domain, file_module, assembly);
4550 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4553 if (assemblyb->type_forwarders)
4554 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4556 /* Emit MANIFESTRESOURCE table */
4558 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4560 MonoReflectionModuleBuilder *file_module =
4561 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4562 /* The table for the main module is emitted later */
4563 if (file_module != moduleb) {
4565 if (file_module->resources) {
4566 int len = mono_array_length (file_module->resources);
4567 for (j = 0; j < len; ++j) {
4568 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4569 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4576 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4579 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4580 * for the modulebuilder @moduleb.
4581 * At the end of the process, method and field tokens are fixed up and the
4582 * on-disk compressed metadata representation is created.
4585 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4587 MonoDynamicTable *table;
4588 MonoDynamicImage *assembly;
4589 MonoReflectionAssemblyBuilder *assemblyb;
4595 assemblyb = moduleb->assemblyb;
4596 assembly = moduleb->dynamic_image;
4597 domain = mono_object_domain (assemblyb);
4599 if (assembly->text_rva)
4602 assembly->text_rva = START_TEXT_RVA;
4604 if (moduleb->is_main) {
4605 mono_image_emit_manifest (moduleb);
4608 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4609 table->rows = 1; /* .<Module> */
4611 alloc_table (table, table->rows);
4613 * Set the first entry.
4615 values = table->values + table->columns;
4616 values [MONO_TYPEDEF_FLAGS] = 0;
4617 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4618 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4619 values [MONO_TYPEDEF_EXTENDS] = 0;
4620 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4621 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4624 * handle global methods
4625 * FIXME: test what to do when global methods are defined in multiple modules.
4627 if (moduleb->global_methods) {
4628 table = &assembly->tables [MONO_TABLE_METHOD];
4629 table->rows += mono_array_length (moduleb->global_methods);
4630 alloc_table (table, table->rows);
4631 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4632 mono_image_get_method_info (
4633 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4635 if (moduleb->global_fields) {
4636 table = &assembly->tables [MONO_TABLE_FIELD];
4637 table->rows += mono_array_length (moduleb->global_fields);
4638 alloc_table (table, table->rows);
4639 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4640 mono_image_get_field_info (
4641 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4644 table = &assembly->tables [MONO_TABLE_MODULE];
4645 alloc_table (table, 1);
4646 mono_image_fill_module_table (domain, moduleb, assembly);
4648 /* Collect all types into a list sorted by their table_idx */
4649 mono_ptr_array_init (types, moduleb->num_types);
4652 for (i = 0; i < moduleb->num_types; ++i) {
4653 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4654 collect_types (&types, type);
4657 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4658 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4659 table->rows += mono_ptr_array_size (types);
4660 alloc_table (table, table->rows);
4663 * Emit type names + namespaces at one place inside the string heap,
4664 * so load_class_names () needs to touch fewer pages.
4666 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4668 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4670 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4671 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4672 string_heap_insert_mstring (&assembly->sheap, tb->name);
4675 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4676 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4677 mono_image_get_type_info (domain, type, assembly);
4681 * table->rows is already set above and in mono_image_fill_module_table.
4683 /* add all the custom attributes at the end, once all the indexes are stable */
4684 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4686 /* CAS assembly permissions */
4687 if (assemblyb->permissions_minimum)
4688 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4689 if (assemblyb->permissions_optional)
4690 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4691 if (assemblyb->permissions_refused)
4692 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4694 module_add_cattrs (assembly, moduleb);
4697 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4699 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4700 * the final tokens and don't need another fixup pass. */
4702 if (moduleb->global_methods) {
4703 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4704 MonoReflectionMethodBuilder *mb = mono_array_get (
4705 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4706 mono_image_add_methodimpl (assembly, mb);
4710 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4711 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4712 if (type->methods) {
4713 for (j = 0; j < type->num_methods; ++j) {
4714 MonoReflectionMethodBuilder *mb = mono_array_get (
4715 type->methods, MonoReflectionMethodBuilder*, j);
4717 mono_image_add_methodimpl (assembly, mb);
4722 mono_ptr_array_destroy (types);
4724 fixup_cattrs (assembly);
4727 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4730 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4732 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4735 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4739 guint32 import_lookup_table;
4743 guint32 import_address_table_rva;
4751 #ifndef DISABLE_REFLECTION_EMIT
4754 * mono_image_insert_string:
4755 * @module: module builder object
4758 * Insert @str into the user string stream of @module.
4761 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4763 MonoDynamicImage *assembly;
4768 MONO_ARCH_SAVE_REGS;
4770 if (!module->dynamic_image)
4771 mono_image_module_basic_init (module);
4773 assembly = module->dynamic_image;
4775 if (assembly->save) {
4776 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4777 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4778 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4780 char *swapped = g_malloc (2 * mono_string_length (str));
4781 const char *p = (const char*)mono_string_chars (str);
4783 swap_with_size (swapped, p, 2, mono_string_length (str));
4784 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4788 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4790 mono_image_add_stream_data (&assembly->us, "", 1);
4792 idx = assembly->us.index ++;
4795 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4797 return MONO_TOKEN_STRING | idx;
4801 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4805 MonoMethodSignature *sig;
4807 klass = obj->vtable->klass;
4808 if (strcmp (klass->name, "MonoMethod") == 0) {
4809 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4810 MonoMethodSignature *old;
4811 guint32 sig_token, parent;
4814 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4816 nargs = mono_array_length (opt_param_types);
4817 old = mono_method_signature (method);
4818 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4820 sig->hasthis = old->hasthis;
4821 sig->explicit_this = old->explicit_this;
4822 sig->call_convention = old->call_convention;
4823 sig->generic_param_count = old->generic_param_count;
4824 sig->param_count = old->param_count + nargs;
4825 sig->sentinelpos = old->param_count;
4826 sig->ret = old->ret;
4828 for (i = 0; i < old->param_count; i++)
4829 sig->params [i] = old->params [i];
4831 for (i = 0; i < nargs; i++) {
4832 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4833 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4836 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4837 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4838 parent >>= MONO_TYPEDEFORREF_BITS;
4840 parent <<= MONO_MEMBERREF_PARENT_BITS;
4841 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4843 sig_token = method_encode_signature (assembly, sig);
4844 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4845 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4846 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4847 ReflectionMethodBuilder rmb;
4848 guint32 parent, sig_token;
4849 int nopt_args, nparams, ngparams, i;
4852 reflection_methodbuilder_from_method_builder (&rmb, mb);
4853 rmb.opt_types = opt_param_types;
4854 nopt_args = mono_array_length (opt_param_types);
4856 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4857 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4858 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4860 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4861 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4862 sig->call_convention = rmb.call_conv;
4863 sig->generic_param_count = ngparams;
4864 sig->param_count = nparams + nopt_args;
4865 sig->sentinelpos = nparams;
4866 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4868 for (i = 0; i < nparams; i++) {
4869 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4870 sig->params [i] = mono_reflection_type_get_handle (rt);
4873 for (i = 0; i < nopt_args; i++) {
4874 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4875 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4878 sig_token = method_builder_encode_signature (assembly, &rmb);
4880 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4881 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4883 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4884 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4886 name = mono_string_to_utf8 (rmb.name);
4887 token = mono_image_get_varargs_method_token (
4888 assembly, parent, name, sig_token);
4891 g_error ("requested method token for %s\n", klass->name);
4894 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4895 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4900 * mono_image_create_token:
4901 * @assembly: a dynamic assembly
4903 * @register_token: Whenever to register the token in the assembly->tokens hash.
4905 * Get a token to insert in the IL code stream for the given MemberInfo.
4906 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4907 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4911 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4912 gboolean create_open_instance, gboolean register_token)
4917 klass = obj->vtable->klass;
4919 /* Check for user defined reflection objects */
4920 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4921 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4922 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4924 if (strcmp (klass->name, "MethodBuilder") == 0) {
4925 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4926 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4928 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4929 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4931 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4932 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4933 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4934 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4935 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4937 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4938 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4940 token = mono_image_get_ctorbuilder_token (assembly, mb);
4941 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4942 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4943 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4944 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4945 if (tb->generic_params) {
4946 token = mono_image_get_generic_field_token (assembly, fb);
4948 if (tb->module->dynamic_image == assembly) {
4949 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4951 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4954 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4955 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4956 if (create_open_instance && tb->generic_params) {
4958 init_type_builder_generics (obj);
4959 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4961 token = mono_metadata_token_from_dor (token);
4962 } else if (tb->module->dynamic_image == assembly) {
4963 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4966 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4969 } else if (strcmp (klass->name, "MonoType") == 0) {
4970 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4971 MonoClass *mc = mono_class_from_mono_type (type);
4972 token = mono_metadata_token_from_dor (
4973 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4974 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4975 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4976 token = mono_metadata_token_from_dor (
4977 mono_image_typedef_or_ref (assembly, type));
4978 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4979 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4980 token = mono_metadata_token_from_dor (
4981 mono_image_typedef_or_ref (assembly, type));
4982 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4983 strcmp (klass->name, "MonoMethod") == 0 ||
4984 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4985 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4986 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4987 if (m->method->is_inflated) {
4988 if (create_open_instance)
4989 token = mono_image_get_methodspec_token (assembly, m->method);
4991 token = mono_image_get_inflated_method_token (assembly, m->method);
4992 } else if ((m->method->klass->image == &assembly->image) &&
4993 !m->method->klass->generic_class) {
4994 static guint32 method_table_idx = 0xffffff;
4995 if (m->method->klass->wastypebuilder) {
4996 /* we use the same token as the one that was assigned
4997 * to the Methodbuilder.
4998 * FIXME: do the equivalent for Fields.
5000 token = m->method->token;
5003 * Each token should have a unique index, but the indexes are
5004 * assigned by managed code, so we don't know about them. An
5005 * easy solution is to count backwards...
5007 method_table_idx --;
5008 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5011 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5013 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5014 } else if (strcmp (klass->name, "MonoField") == 0) {
5015 MonoReflectionField *f = (MonoReflectionField *)obj;
5016 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5017 static guint32 field_table_idx = 0xffffff;
5019 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5021 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5023 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5024 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5025 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5026 token = mono_image_get_array_token (assembly, m);
5027 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5028 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5029 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5030 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5031 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5032 token = mono_metadata_token_from_dor (
5033 mono_image_typedef_or_ref (assembly, type));
5034 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5035 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5036 token = mono_image_get_field_on_inst_token (assembly, f);
5037 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5038 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5039 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5040 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5041 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5042 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5043 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5044 MonoReflectionType *type = (MonoReflectionType *)obj;
5045 token = mono_metadata_token_from_dor (
5046 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5048 g_error ("requested token for %s\n", klass->name);
5052 mono_image_register_token (assembly, token, obj);
5058 * mono_image_register_token:
5060 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5061 * the Module.ResolveXXXToken () methods to work.
5064 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5066 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5068 /* There could be multiple MethodInfo objects with the same token */
5069 //g_assert (prev == obj);
5071 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5075 static MonoDynamicImage*
5076 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5078 static const guchar entrycode [16] = {0xff, 0x25, 0};
5079 MonoDynamicImage *image;
5082 const char *version;
5084 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5085 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5087 version = mono_get_runtime_info ()->runtime_version;
5090 /* The MonoGHashTable's need GC tracking */
5091 image = GC_MALLOC (sizeof (MonoDynamicImage));
5093 image = g_new0 (MonoDynamicImage, 1);
5096 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5098 /*g_print ("created image %p\n", image);*/
5099 /* keep in sync with image.c */
5100 image->image.name = assembly_name;
5101 image->image.assembly_name = image->image.name; /* they may be different */
5102 image->image.module_name = module_name;
5103 image->image.version = g_strdup (version);
5104 image->image.md_version_major = 1;
5105 image->image.md_version_minor = 1;
5106 image->image.dynamic = TRUE;
5108 image->image.references = g_new0 (MonoAssembly*, 1);
5109 image->image.references [0] = NULL;
5111 mono_image_init (&image->image);
5113 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5114 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5115 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5116 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5117 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5118 image->handleref = g_hash_table_new (NULL, NULL);
5119 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5120 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5122 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5123 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5125 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5126 image->gen_params = g_ptr_array_new ();
5127 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5129 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5130 string_heap_init (&image->sheap);
5131 mono_image_add_stream_data (&image->us, "", 1);
5132 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5133 /* import tables... */
5134 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5135 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5136 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5137 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5138 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5139 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5140 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5141 stream_data_align (&image->code);
5143 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5145 for (i=0; i < MONO_TABLE_NUM; ++i) {
5146 image->tables [i].next_idx = 1;
5147 image->tables [i].columns = table_sizes [i];
5150 image->image.assembly = (MonoAssembly*)assembly;
5151 image->run = assembly->run;
5152 image->save = assembly->save;
5153 image->pe_kind = 0x1; /* ILOnly */
5154 image->machine = 0x14c; /* I386 */
5156 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5163 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5169 release_hashtable (MonoGHashTable **hash)
5172 mono_g_hash_table_destroy (*hash);
5178 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5180 release_hashtable (&image->token_fixups);
5181 release_hashtable (&image->handleref_managed);
5182 release_hashtable (&image->tokens);
5183 release_hashtable (&image->remapped_tokens);
5184 release_hashtable (&image->generic_def_objects);
5185 release_hashtable (&image->methodspec);
5189 mono_dynamic_image_free (MonoDynamicImage *image)
5191 MonoDynamicImage *di = image;
5196 mono_g_hash_table_destroy (di->methodspec);
5198 g_hash_table_destroy (di->typespec);
5200 g_hash_table_destroy (di->typeref);
5202 g_hash_table_destroy (di->handleref);
5203 if (di->handleref_managed)
5204 mono_g_hash_table_destroy (di->handleref_managed);
5206 mono_g_hash_table_destroy (di->tokens);
5207 if (di->remapped_tokens)
5208 mono_g_hash_table_destroy (di->remapped_tokens);
5209 if (di->generic_def_objects)
5210 mono_g_hash_table_destroy (di->generic_def_objects);
5211 if (di->blob_cache) {
5212 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5213 g_hash_table_destroy (di->blob_cache);
5215 if (di->standalonesig_cache)
5216 g_hash_table_destroy (di->standalonesig_cache);
5217 for (list = di->array_methods; list; list = list->next) {
5218 ArrayMethod *am = (ArrayMethod *)list->data;
5223 g_list_free (di->array_methods);
5224 if (di->gen_params) {
5225 for (i = 0; i < di->gen_params->len; i++) {
5226 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5227 mono_gc_deregister_root ((char*) &entry->gparam);
5230 g_ptr_array_free (di->gen_params, TRUE);
5232 if (di->token_fixups)
5233 mono_g_hash_table_destroy (di->token_fixups);
5234 if (di->method_to_table_idx)
5235 g_hash_table_destroy (di->method_to_table_idx);
5236 if (di->field_to_table_idx)
5237 g_hash_table_destroy (di->field_to_table_idx);
5238 if (di->method_aux_hash)
5239 g_hash_table_destroy (di->method_aux_hash);
5240 if (di->vararg_aux_hash)
5241 g_hash_table_destroy (di->vararg_aux_hash);
5242 g_free (di->strong_name);
5243 g_free (di->win32_res);
5245 g_free (di->public_key);
5247 /*g_print ("string heap destroy for image %p\n", di);*/
5248 mono_dynamic_stream_reset (&di->sheap);
5249 mono_dynamic_stream_reset (&di->code);
5250 mono_dynamic_stream_reset (&di->resources);
5251 mono_dynamic_stream_reset (&di->us);
5252 mono_dynamic_stream_reset (&di->blob);
5253 mono_dynamic_stream_reset (&di->tstream);
5254 mono_dynamic_stream_reset (&di->guid);
5255 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5256 g_free (di->tables [i].values);
5260 #ifndef DISABLE_REFLECTION_EMIT
5263 * mono_image_basic_init:
5264 * @assembly: an assembly builder object
5266 * Create the MonoImage that represents the assembly builder and setup some
5267 * of the helper hash table and the basic metadata streams.
5270 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5272 MonoDynamicAssembly *assembly;
5273 MonoDynamicImage *image;
5274 MonoDomain *domain = mono_object_domain (assemblyb);
5276 MONO_ARCH_SAVE_REGS;
5278 if (assemblyb->dynamic_assembly)
5282 /* assembly->assembly.image might be GC allocated */
5283 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5285 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5288 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5290 assembly->assembly.ref_count = 1;
5291 assembly->assembly.dynamic = TRUE;
5292 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5293 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5294 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5295 if (assemblyb->culture)
5296 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5298 assembly->assembly.aname.culture = g_strdup ("");
5300 if (assemblyb->version) {
5301 char *vstr = mono_string_to_utf8 (assemblyb->version);
5302 char **version = g_strsplit (vstr, ".", 4);
5303 char **parts = version;
5304 assembly->assembly.aname.major = atoi (*parts++);
5305 assembly->assembly.aname.minor = atoi (*parts++);
5306 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5307 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5309 g_strfreev (version);
5312 assembly->assembly.aname.major = 0;
5313 assembly->assembly.aname.minor = 0;
5314 assembly->assembly.aname.build = 0;
5315 assembly->assembly.aname.revision = 0;
5318 assembly->run = assemblyb->access != 2;
5319 assembly->save = assemblyb->access != 1;
5320 assembly->domain = domain;
5322 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5323 image->initial_image = TRUE;
5324 assembly->assembly.aname.name = image->image.name;
5325 assembly->assembly.image = &image->image;
5326 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5327 /* -1 to correct for the trailing NULL byte */
5328 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5329 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5331 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5334 mono_domain_assemblies_lock (domain);
5335 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5336 mono_domain_assemblies_unlock (domain);
5338 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5340 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5342 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5345 #endif /* !DISABLE_REFLECTION_EMIT */
5347 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5350 calc_section_size (MonoDynamicImage *assembly)
5354 /* alignment constraints */
5355 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5356 g_assert ((assembly->code.index % 4) == 0);
5357 assembly->meta_size += 3;
5358 assembly->meta_size &= ~3;
5359 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5360 g_assert ((assembly->resources.index % 4) == 0);
5362 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5363 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5366 if (assembly->win32_res) {
5367 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5369 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5370 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5374 assembly->sections [MONO_SECTION_RELOC].size = 12;
5375 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5385 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5389 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5391 ResTreeNode *t1 = (ResTreeNode*)a;
5392 ResTreeNode *t2 = (ResTreeNode*)b;
5394 return t1->id - t2->id;
5398 * resource_tree_create:
5400 * Organize the resources into a resource tree.
5402 static ResTreeNode *
5403 resource_tree_create (MonoArray *win32_resources)
5405 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5409 tree = g_new0 (ResTreeNode, 1);
5411 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5412 MonoReflectionWin32Resource *win32_res =
5413 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5417 /* FIXME: BUG: this stores managed references in unmanaged memory */
5418 lang_node = g_new0 (ResTreeNode, 1);
5419 lang_node->id = win32_res->lang_id;
5420 lang_node->win32_res = win32_res;
5422 /* Create type node if neccesary */
5424 for (l = tree->children; l; l = l->next)
5425 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5426 type_node = (ResTreeNode*)l->data;
5431 type_node = g_new0 (ResTreeNode, 1);
5432 type_node->id = win32_res->res_type;
5435 * The resource types have to be sorted otherwise
5436 * Windows Explorer can't display the version information.
5438 tree->children = g_slist_insert_sorted (tree->children,
5439 type_node, resource_tree_compare_by_id);
5442 /* Create res node if neccesary */
5444 for (l = type_node->children; l; l = l->next)
5445 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5446 res_node = (ResTreeNode*)l->data;
5451 res_node = g_new0 (ResTreeNode, 1);
5452 res_node->id = win32_res->res_id;
5453 type_node->children = g_slist_append (type_node->children, res_node);
5456 res_node->children = g_slist_append (res_node->children, lang_node);
5463 * resource_tree_encode:
5465 * Encode the resource tree into the format used in the PE file.
5468 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5471 MonoPEResourceDir dir;
5472 MonoPEResourceDirEntry dir_entry;
5473 MonoPEResourceDataEntry data_entry;
5475 guint32 res_id_entries;
5478 * For the format of the resource directory, see the article
5479 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5483 memset (&dir, 0, sizeof (dir));
5484 memset (&dir_entry, 0, sizeof (dir_entry));
5485 memset (&data_entry, 0, sizeof (data_entry));
5487 g_assert (sizeof (dir) == 16);
5488 g_assert (sizeof (dir_entry) == 8);
5489 g_assert (sizeof (data_entry) == 16);
5491 node->offset = p - begin;
5493 /* IMAGE_RESOURCE_DIRECTORY */
5494 res_id_entries = g_slist_length (node->children);
5495 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5497 memcpy (p, &dir, sizeof (dir));
5500 /* Reserve space for entries */
5502 p += sizeof (dir_entry) * res_id_entries;
5504 /* Write children */
5505 for (l = node->children; l; l = l->next) {
5506 ResTreeNode *child = (ResTreeNode*)l->data;
5508 if (child->win32_res) {
5511 child->offset = p - begin;
5513 /* IMAGE_RESOURCE_DATA_ENTRY */
5514 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5515 size = mono_array_length (child->win32_res->res_data);
5516 data_entry.rde_size = GUINT32_TO_LE (size);
5518 memcpy (p, &data_entry, sizeof (data_entry));
5519 p += sizeof (data_entry);
5521 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5524 resource_tree_encode (child, begin, p, &p);
5528 /* IMAGE_RESOURCE_ENTRY */
5529 for (l = node->children; l; l = l->next) {
5530 ResTreeNode *child = (ResTreeNode*)l->data;
5532 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5533 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5535 memcpy (entries, &dir_entry, sizeof (dir_entry));
5536 entries += sizeof (dir_entry);
5543 resource_tree_free (ResTreeNode * node)
5546 for (list = node->children; list; list = list->next)
5547 resource_tree_free ((ResTreeNode*)list->data);
5548 g_slist_free(node->children);
5553 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5558 MonoReflectionWin32Resource *win32_res;
5561 if (!assemblyb->win32_resources)
5565 * Resources are stored in a three level tree inside the PE file.
5566 * - level one contains a node for each type of resource
5567 * - level two contains a node for each resource
5568 * - level three contains a node for each instance of a resource for a
5569 * specific language.
5572 tree = resource_tree_create (assemblyb->win32_resources);
5574 /* Estimate the size of the encoded tree */
5576 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5577 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5578 size += mono_array_length (win32_res->res_data);
5580 /* Directory structure */
5581 size += mono_array_length (assemblyb->win32_resources) * 256;
5582 p = buf = g_malloc (size);
5584 resource_tree_encode (tree, p, p, &p);
5586 g_assert (p - buf <= size);
5588 assembly->win32_res = g_malloc (p - buf);
5589 assembly->win32_res_size = p - buf;
5590 memcpy (assembly->win32_res, buf, p - buf);
5593 resource_tree_free (tree);
5597 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5599 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5602 p += sizeof (MonoPEResourceDir);
5603 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5604 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5605 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5606 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5607 fixup_resource_directory (res_section, child, rva);
5609 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5610 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5613 p += sizeof (MonoPEResourceDirEntry);
5618 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5621 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5622 g_error ("WriteFile returned %d\n", GetLastError ());
5626 * mono_image_create_pefile:
5627 * @mb: a module builder object
5629 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5630 * assembly->pefile where it can be easily retrieved later in chunks.
5633 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5635 MonoMSDOSHeader *msdos;
5636 MonoDotNetHeader *header;
5637 MonoSectionTable *section;
5638 MonoCLIHeader *cli_header;
5639 guint32 size, image_size, virtual_base, text_offset;
5640 guint32 header_start, section_start, file_offset, virtual_offset;
5641 MonoDynamicImage *assembly;
5642 MonoReflectionAssemblyBuilder *assemblyb;
5643 MonoDynamicStream pefile_stream = {0};
5644 MonoDynamicStream *pefile = &pefile_stream;
5646 guint32 *rva, value;
5648 static const unsigned char msheader[] = {
5649 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5650 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5653 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5654 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5655 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5656 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5659 assemblyb = mb->assemblyb;
5661 mono_image_basic_init (assemblyb);
5662 assembly = mb->dynamic_image;
5664 assembly->pe_kind = assemblyb->pe_kind;
5665 assembly->machine = assemblyb->machine;
5666 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5667 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5669 mono_image_build_metadata (mb);
5671 if (mb->is_main && assemblyb->resources) {
5672 int len = mono_array_length (assemblyb->resources);
5673 for (i = 0; i < len; ++i)
5674 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5677 if (mb->resources) {
5678 int len = mono_array_length (mb->resources);
5679 for (i = 0; i < len; ++i)
5680 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5683 build_compressed_metadata (assembly);
5686 assembly_add_win32_resources (assembly, assemblyb);
5688 nsections = calc_section_size (assembly);
5690 /* The DOS header and stub */
5691 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5692 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5694 /* the dotnet header */
5695 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5697 /* the section tables */
5698 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5700 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5701 virtual_offset = VIRT_ALIGN;
5704 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5705 if (!assembly->sections [i].size)
5708 file_offset += FILE_ALIGN - 1;
5709 file_offset &= ~(FILE_ALIGN - 1);
5710 virtual_offset += VIRT_ALIGN - 1;
5711 virtual_offset &= ~(VIRT_ALIGN - 1);
5713 assembly->sections [i].offset = file_offset;
5714 assembly->sections [i].rva = virtual_offset;
5716 file_offset += assembly->sections [i].size;
5717 virtual_offset += assembly->sections [i].size;
5718 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5721 file_offset += FILE_ALIGN - 1;
5722 file_offset &= ~(FILE_ALIGN - 1);
5724 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5726 /* back-patch info */
5727 msdos = (MonoMSDOSHeader*)pefile->data;
5728 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5730 header = (MonoDotNetHeader*)(pefile->data + header_start);
5731 header->pesig [0] = 'P';
5732 header->pesig [1] = 'E';
5734 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5735 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5736 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5737 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5738 if (assemblyb->pekind == 1) {
5740 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5743 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5746 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5748 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5749 header->pe.pe_major = 6;
5750 header->pe.pe_minor = 0;
5751 size = assembly->sections [MONO_SECTION_TEXT].size;
5752 size += FILE_ALIGN - 1;
5753 size &= ~(FILE_ALIGN - 1);
5754 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5755 size = assembly->sections [MONO_SECTION_RSRC].size;
5756 size += FILE_ALIGN - 1;
5757 size &= ~(FILE_ALIGN - 1);
5758 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5759 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5760 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5761 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5762 /* pe_rva_entry_point always at the beginning of the text section */
5763 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5765 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5766 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5767 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5768 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5769 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5770 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5771 size = section_start;
5772 size += FILE_ALIGN - 1;
5773 size &= ~(FILE_ALIGN - 1);
5774 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5776 size += VIRT_ALIGN - 1;
5777 size &= ~(VIRT_ALIGN - 1);
5778 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5781 // Translate the PEFileKind value to the value expected by the Windows loader
5787 // PEFileKinds.Dll == 1
5788 // PEFileKinds.ConsoleApplication == 2
5789 // PEFileKinds.WindowApplication == 3
5792 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5793 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5795 if (assemblyb->pekind == 3)
5800 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5802 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5803 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5804 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5805 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5806 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5807 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5809 /* fill data directory entries */
5811 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5812 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5814 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5815 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5817 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5818 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5819 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5820 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5821 /* patch entrypoint name */
5822 if (assemblyb->pekind == 1)
5823 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5825 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5826 /* patch imported function RVA name */
5827 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5828 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5830 /* the import table */
5831 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5832 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5833 /* patch imported dll RVA name and other entries in the dir */
5834 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5835 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5836 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5837 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5838 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5839 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5841 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5842 value = (assembly->text_rva + assembly->imp_names_offset);
5843 *p++ = (value) & 0xff;
5844 *p++ = (value >> 8) & (0xff);
5845 *p++ = (value >> 16) & (0xff);
5846 *p++ = (value >> 24) & (0xff);
5848 /* the CLI header info */
5849 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5850 cli_header->ch_size = GUINT32_FROM_LE (72);
5851 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5852 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5853 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5854 if (assemblyb->entry_point) {
5855 guint32 table_idx = 0;
5856 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5857 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5858 table_idx = methodb->table_idx;
5860 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5862 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5864 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5866 /* The embedded managed resources */
5867 text_offset = assembly->text_rva + assembly->code.index;
5868 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5869 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5870 text_offset += assembly->resources.index;
5871 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5872 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5873 text_offset += assembly->meta_size;
5874 if (assembly->strong_name_size) {
5875 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5876 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5877 text_offset += assembly->strong_name_size;
5880 /* write the section tables and section content */
5881 section = (MonoSectionTable*)(pefile->data + section_start);
5882 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5883 static const char section_names [][7] = {
5884 ".text", ".rsrc", ".reloc"
5886 if (!assembly->sections [i].size)
5888 strcpy (section->st_name, section_names [i]);
5889 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5890 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5891 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5892 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5893 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5894 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5895 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5899 checked_write_file (file, pefile->data, pefile->index);
5901 mono_dynamic_stream_reset (pefile);
5903 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5904 if (!assembly->sections [i].size)
5907 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5908 g_error ("SetFilePointer returned %d\n", GetLastError ());
5911 case MONO_SECTION_TEXT:
5912 /* patch entry point */
5913 p = (guchar*)(assembly->code.data + 2);
5914 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5915 *p++ = (value) & 0xff;
5916 *p++ = (value >> 8) & 0xff;
5917 *p++ = (value >> 16) & 0xff;
5918 *p++ = (value >> 24) & 0xff;
5920 checked_write_file (file, assembly->code.data, assembly->code.index);
5921 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5922 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5923 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5926 g_free (assembly->image.raw_metadata);
5928 case MONO_SECTION_RELOC: {
5932 guint16 type_and_offset;
5936 g_assert (sizeof (reloc) == 12);
5938 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5939 reloc.block_size = GUINT32_FROM_LE (12);
5942 * the entrypoint is always at the start of the text section
5943 * 3 is IMAGE_REL_BASED_HIGHLOW
5944 * 2 is patch_size_rva - text_rva
5946 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5949 checked_write_file (file, &reloc, sizeof (reloc));
5953 case MONO_SECTION_RSRC:
5954 if (assembly->win32_res) {
5956 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5957 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5958 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5962 g_assert_not_reached ();
5966 /* check that the file is properly padded */
5967 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5968 g_error ("SetFilePointer returned %d\n", GetLastError ());
5969 if (! SetEndOfFile (file))
5970 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5972 mono_dynamic_stream_reset (&assembly->code);
5973 mono_dynamic_stream_reset (&assembly->us);
5974 mono_dynamic_stream_reset (&assembly->blob);
5975 mono_dynamic_stream_reset (&assembly->guid);
5976 mono_dynamic_stream_reset (&assembly->sheap);
5978 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5979 g_hash_table_destroy (assembly->blob_cache);
5980 assembly->blob_cache = NULL;
5983 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5986 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5988 g_assert_not_reached ();
5991 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5993 #ifndef DISABLE_REFLECTION_EMIT
5995 MonoReflectionModule *
5996 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6000 MonoImageOpenStatus status;
6001 MonoDynamicAssembly *assembly;
6002 guint32 module_count;
6003 MonoImage **new_modules;
6004 gboolean *new_modules_loaded;
6006 name = mono_string_to_utf8 (fileName);
6008 image = mono_image_open (name, &status);
6011 if (status == MONO_IMAGE_ERROR_ERRNO)
6012 exc = mono_get_exception_file_not_found (fileName);
6014 exc = mono_get_exception_bad_image_format (name);
6016 mono_raise_exception (exc);
6021 assembly = ab->dynamic_assembly;
6022 image->assembly = (MonoAssembly*)assembly;
6024 module_count = image->assembly->image->module_count;
6025 new_modules = g_new0 (MonoImage *, module_count + 1);
6026 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6028 if (image->assembly->image->modules)
6029 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6030 if (image->assembly->image->modules_loaded)
6031 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6032 new_modules [module_count] = image;
6033 new_modules_loaded [module_count] = TRUE;
6034 mono_image_addref (image);
6036 g_free (image->assembly->image->modules);
6037 image->assembly->image->modules = new_modules;
6038 image->assembly->image->modules_loaded = new_modules_loaded;
6039 image->assembly->image->module_count ++;
6041 mono_assembly_load_references (image, &status);
6043 mono_image_close (image);
6044 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6047 return mono_module_get_object (mono_domain_get (), image);
6050 #endif /* DISABLE_REFLECTION_EMIT */
6053 * We need to return always the same object for MethodInfo, FieldInfo etc..
6054 * but we need to consider the reflected type.
6055 * type uses a different hash, since it uses custom hash/equal functions.
6060 MonoClass *refclass;
6064 reflected_equal (gconstpointer a, gconstpointer b) {
6065 const ReflectedEntry *ea = a;
6066 const ReflectedEntry *eb = b;
6068 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6072 reflected_hash (gconstpointer a) {
6073 const ReflectedEntry *ea = a;
6074 return mono_aligned_addr_hash (ea->item);
6077 #define CHECK_OBJECT(t,p,k) \
6083 mono_domain_lock (domain); \
6084 if (!domain->refobject_hash) \
6085 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6086 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6087 mono_domain_unlock (domain); \
6090 mono_domain_unlock (domain); \
6093 #ifdef HAVE_BOEHM_GC
6094 /* ReflectedEntry doesn't need to be GC tracked */
6095 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6096 #define FREE_REFENTRY(entry) g_free ((entry))
6097 #define REFENTRY_REQUIRES_CLEANUP
6099 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6101 #define FREE_REFENTRY(entry)
6104 #define CACHE_OBJECT(t,p,o,k) \
6107 ReflectedEntry pe; \
6109 pe.refclass = (k); \
6110 mono_domain_lock (domain); \
6111 if (!domain->refobject_hash) \
6112 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6113 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6115 ReflectedEntry *e = ALLOC_REFENTRY; \
6117 e->refclass = (k); \
6118 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6121 mono_domain_unlock (domain); \
6126 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6128 mono_domain_lock (domain);
6129 if (domain->refobject_hash) {
6131 gpointer orig_pe, orig_value;
6134 pe.refclass = klass;
6135 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6136 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6137 FREE_REFENTRY (orig_pe);
6140 mono_domain_unlock (domain);
6143 #ifdef REFENTRY_REQUIRES_CLEANUP
6145 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6147 FREE_REFENTRY (key);
6152 mono_reflection_cleanup_domain (MonoDomain *domain)
6154 if (domain->refobject_hash) {
6155 /*let's avoid scanning the whole hashtable if not needed*/
6156 #ifdef REFENTRY_REQUIRES_CLEANUP
6157 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6159 mono_g_hash_table_destroy (domain->refobject_hash);
6160 domain->refobject_hash = NULL;
6164 #ifndef DISABLE_REFLECTION_EMIT
6166 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6168 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6172 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6174 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6178 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6180 MonoDynamicImage *image = moduleb->dynamic_image;
6181 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6185 MonoImage **new_modules;
6187 char *name, *fqname;
6189 * FIXME: we already created an image in mono_image_basic_init (), but
6190 * we don't know which module it belongs to, since that is only
6191 * determined at assembly save time.
6193 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6194 name = mono_string_to_utf8 (ab->name);
6195 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6196 if (!mono_error_ok (&error)) {
6198 mono_error_raise_exception (&error);
6200 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6202 moduleb->module.image = &image->image;
6203 moduleb->dynamic_image = image;
6204 register_module (mono_object_domain (moduleb), moduleb, image);
6206 /* register the module with the assembly */
6207 ass = ab->dynamic_assembly->assembly.image;
6208 module_count = ass->module_count;
6209 new_modules = g_new0 (MonoImage *, module_count + 1);
6212 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6213 new_modules [module_count] = &image->image;
6214 mono_image_addref (&image->image);
6216 g_free (ass->modules);
6217 ass->modules = new_modules;
6218 ass->module_count ++;
6223 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6225 MonoDynamicImage *image = moduleb->dynamic_image;
6227 g_assert (type->type);
6228 image->wrappers_type = mono_class_from_mono_type (type->type);
6234 * mono_assembly_get_object:
6235 * @domain: an app domain
6236 * @assembly: an assembly
6238 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6240 MonoReflectionAssembly*
6241 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6243 static MonoClass *assembly_type;
6244 MonoReflectionAssembly *res;
6246 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6247 if (!assembly_type) {
6248 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6250 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6252 assembly_type = class;
6254 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6255 res->assembly = assembly;
6257 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6262 MonoReflectionModule*
6263 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6265 static MonoClass *module_type;
6266 MonoReflectionModule *res;
6269 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6271 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6273 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6275 module_type = class;
6277 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6280 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6282 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6283 basename = g_path_get_basename (image->name);
6284 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6285 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6289 if (image->assembly->image == image) {
6290 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6294 if (image->assembly->image->modules) {
6295 for (i = 0; i < image->assembly->image->module_count; i++) {
6296 if (image->assembly->image->modules [i] == image)
6297 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6299 g_assert (res->token);
6303 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6306 MonoReflectionModule*
6307 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6309 static MonoClass *module_type;
6310 MonoReflectionModule *res;
6311 MonoTableInfo *table;
6312 guint32 cols [MONO_FILE_SIZE];
6314 guint32 i, name_idx;
6318 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6320 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6322 module_type = class;
6324 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6326 table = &image->tables [MONO_TABLE_FILE];
6327 g_assert (table_index < table->rows);
6328 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6331 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6332 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6334 /* Check whenever the row has a corresponding row in the moduleref table */
6335 table = &image->tables [MONO_TABLE_MODULEREF];
6336 for (i = 0; i < table->rows; ++i) {
6337 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6338 val = mono_metadata_string_heap (image, name_idx);
6339 if (strcmp (val, name) == 0)
6340 res->image = image->modules [i];
6343 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6344 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6345 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6346 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6347 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6353 verify_safe_for_managed_space (MonoType *type)
6355 switch (type->type) {
6357 case MONO_TYPE_ARRAY:
6358 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6360 return verify_safe_for_managed_space (type->data.type);
6361 case MONO_TYPE_SZARRAY:
6362 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6363 case MONO_TYPE_GENERICINST: {
6364 MonoGenericInst *inst = type->data.generic_class->inst;
6368 for (i = 0; i < inst->type_argc; ++i)
6369 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6375 case MONO_TYPE_MVAR:
6382 mono_type_normalize (MonoType *type)
6385 MonoGenericClass *gclass;
6386 MonoGenericInst *ginst;
6388 MonoGenericContainer *gcontainer;
6389 MonoType **argv = NULL;
6390 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6392 if (type->type != MONO_TYPE_GENERICINST)
6395 gclass = type->data.generic_class;
6396 ginst = gclass->context.class_inst;
6397 if (!ginst->is_open)
6400 gtd = gclass->container_class;
6401 gcontainer = gtd->generic_container;
6402 argv = g_newa (MonoType*, ginst->type_argc);
6404 for (i = 0; i < ginst->type_argc; ++i) {
6405 MonoType *t = ginst->type_argv [i], *norm;
6406 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6407 is_denorm_gtd = FALSE;
6408 norm = mono_type_normalize (t);
6411 requires_rebind = TRUE;
6415 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6417 if (requires_rebind) {
6418 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6419 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6425 * mono_type_get_object:
6426 * @domain: an app domain
6429 * Return an System.MonoType object representing the type @type.
6432 mono_type_get_object (MonoDomain *domain, MonoType *type)
6434 MonoType *norm_type;
6435 MonoReflectionType *res;
6436 MonoClass *klass = mono_class_from_mono_type (type);
6438 /*we must avoid using @type as it might have come
6439 * from a mono_metadata_type_dup and the caller
6440 * expects that is can be freed.
6441 * Using the right type from
6443 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6445 /* void is very common */
6446 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6447 return (MonoReflectionType*)domain->typeof_void;
6450 * If the vtable of the given class was already created, we can use
6451 * the MonoType from there and avoid all locking and hash table lookups.
6453 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6454 * that the resulting object is different.
6456 if (type == &klass->byval_arg && !klass->image->dynamic) {
6457 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6458 if (vtable && vtable->type)
6459 return vtable->type;
6462 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6463 mono_domain_lock (domain);
6464 if (!domain->type_hash)
6465 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6466 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6467 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6468 mono_domain_unlock (domain);
6469 mono_loader_unlock ();
6473 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6474 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6475 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6476 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6477 * artifact of how generics are encoded and should be transparent to managed code so we
6478 * need to weed out this diference when retrieving managed System.Type objects.
6480 norm_type = mono_type_normalize (type);
6481 if (norm_type != type) {
6482 res = mono_type_get_object (domain, norm_type);
6483 mono_g_hash_table_insert (domain->type_hash, type, res);
6484 mono_domain_unlock (domain);
6485 mono_loader_unlock ();
6489 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6490 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6493 if (!verify_safe_for_managed_space (type)) {
6494 mono_domain_unlock (domain);
6495 mono_loader_unlock ();
6496 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6499 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6500 gboolean is_type_done = TRUE;
6501 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6502 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6503 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6505 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6506 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6508 if (gparam->owner && gparam->owner->is_method) {
6509 MonoMethod *method = gparam->owner->owner.method;
6510 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6511 is_type_done = FALSE;
6512 } else if (gparam->owner && !gparam->owner->is_method) {
6513 MonoClass *klass = gparam->owner->owner.klass;
6514 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6515 is_type_done = FALSE;
6519 /* g_assert_not_reached (); */
6520 /* should this be considered an error condition? */
6521 if (is_type_done && !type->byref) {
6522 mono_domain_unlock (domain);
6523 mono_loader_unlock ();
6524 return mono_class_get_ref_info (klass);
6527 /* This is stored in vtables/JITted code so it has to be pinned */
6528 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6530 mono_g_hash_table_insert (domain->type_hash, type, res);
6532 if (type->type == MONO_TYPE_VOID)
6533 domain->typeof_void = (MonoObject*)res;
6535 mono_domain_unlock (domain);
6536 mono_loader_unlock ();
6541 * mono_method_get_object:
6542 * @domain: an app domain
6544 * @refclass: the reflected type (can be NULL)
6546 * Return an System.Reflection.MonoMethod object representing the method @method.
6548 MonoReflectionMethod*
6549 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6552 * We use the same C representation for methods and constructors, but the type
6553 * name in C# is different.
6555 static MonoClass *System_Reflection_MonoMethod = NULL;
6556 static MonoClass *System_Reflection_MonoCMethod = NULL;
6557 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6558 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6560 MonoReflectionMethod *ret;
6562 if (method->is_inflated) {
6563 MonoReflectionGenericMethod *gret;
6565 refclass = method->klass;
6566 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6567 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6568 if (!System_Reflection_MonoGenericCMethod)
6569 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6570 klass = System_Reflection_MonoGenericCMethod;
6572 if (!System_Reflection_MonoGenericMethod)
6573 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6574 klass = System_Reflection_MonoGenericMethod;
6576 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6577 gret->method.method = method;
6578 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6579 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6580 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6584 refclass = method->klass;
6586 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6587 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6588 if (!System_Reflection_MonoCMethod)
6589 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6590 klass = System_Reflection_MonoCMethod;
6593 if (!System_Reflection_MonoMethod)
6594 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6595 klass = System_Reflection_MonoMethod;
6597 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6598 ret->method = method;
6599 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6600 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6604 * mono_method_clear_object:
6606 * Clear the cached reflection objects for the dynamic method METHOD.
6609 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6612 g_assert (method->dynamic);
6614 klass = method->klass;
6616 clear_cached_object (domain, method, klass);
6617 klass = klass->parent;
6619 /* Added by mono_param_get_objects () */
6620 clear_cached_object (domain, &(method->signature), NULL);
6621 klass = method->klass;
6623 clear_cached_object (domain, &(method->signature), klass);
6624 klass = klass->parent;
6629 * mono_field_get_object:
6630 * @domain: an app domain
6634 * Return an System.Reflection.MonoField object representing the field @field
6637 MonoReflectionField*
6638 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6640 MonoReflectionField *res;
6641 static MonoClass *monofield_klass;
6643 CHECK_OBJECT (MonoReflectionField *, field, klass);
6644 if (!monofield_klass)
6645 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6646 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6649 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6651 if (is_field_on_inst (field)) {
6652 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6653 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6656 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6657 res->attrs = mono_field_get_flags (field);
6659 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6663 * mono_property_get_object:
6664 * @domain: an app domain
6666 * @property: a property
6668 * Return an System.Reflection.MonoProperty object representing the property @property
6671 MonoReflectionProperty*
6672 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6674 MonoReflectionProperty *res;
6675 static MonoClass *monoproperty_klass;
6677 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6678 if (!monoproperty_klass)
6679 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6680 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6682 res->property = property;
6683 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6687 * mono_event_get_object:
6688 * @domain: an app domain
6692 * Return an System.Reflection.MonoEvent object representing the event @event
6695 MonoReflectionEvent*
6696 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6698 MonoReflectionEvent *res;
6699 MonoReflectionMonoEvent *mono_event;
6700 static MonoClass *monoevent_klass;
6702 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6703 if (!monoevent_klass)
6704 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6705 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6706 mono_event->klass = klass;
6707 mono_event->event = event;
6708 res = (MonoReflectionEvent*)mono_event;
6709 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6713 * mono_get_reflection_missing_object:
6714 * @domain: Domain where the object lives
6716 * Returns the System.Reflection.Missing.Value singleton object
6717 * (of type System.Reflection.Missing).
6719 * Used as the value for ParameterInfo.DefaultValue when Optional
6723 mono_get_reflection_missing_object (MonoDomain *domain)
6726 static MonoClassField *missing_value_field = NULL;
6728 if (!missing_value_field) {
6729 MonoClass *missing_klass;
6730 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6731 mono_class_init (missing_klass);
6732 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6733 g_assert (missing_value_field);
6735 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6741 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6744 *dbnull = mono_get_dbnull_object (domain);
6749 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6751 if (!*reflection_missing)
6752 *reflection_missing = mono_get_reflection_missing_object (domain);
6753 return *reflection_missing;
6757 * mono_param_get_objects:
6758 * @domain: an app domain
6761 * Return an System.Reflection.ParameterInfo array object representing the parameters
6762 * in the method @method.
6765 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6767 static MonoClass *System_Reflection_ParameterInfo;
6768 static MonoClass *System_Reflection_ParameterInfo_array;
6770 MonoArray *res = NULL;
6771 MonoReflectionMethod *member = NULL;
6772 MonoReflectionParameter *param = NULL;
6773 char **names, **blobs = NULL;
6774 guint32 *types = NULL;
6775 MonoType *type = NULL;
6776 MonoObject *dbnull = NULL;
6777 MonoObject *missing = NULL;
6778 MonoMarshalSpec **mspecs;
6779 MonoMethodSignature *sig;
6780 MonoVTable *pinfo_vtable;
6783 if (!System_Reflection_ParameterInfo_array) {
6786 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6787 mono_memory_barrier ();
6788 System_Reflection_ParameterInfo = klass;
6790 klass = mono_array_class_get (klass, 1);
6791 mono_memory_barrier ();
6792 System_Reflection_ParameterInfo_array = klass;
6795 sig = mono_method_signature_checked (method, &error);
6796 if (!mono_error_ok (&error))
6797 mono_error_raise_exception (&error);
6799 if (!sig->param_count)
6800 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6802 /* Note: the cache is based on the address of the signature into the method
6803 * since we already cache MethodInfos with the method as keys.
6805 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6807 member = mono_method_get_object (domain, method, refclass);
6808 names = g_new (char *, sig->param_count);
6809 mono_method_get_param_names (method, (const char **) names);
6811 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6812 mono_method_get_marshal_info (method, mspecs);
6814 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6815 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6816 for (i = 0; i < sig->param_count; ++i) {
6817 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6818 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6819 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6820 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6821 param->PositionImpl = i;
6822 param->AttrsImpl = sig->params [i]->attrs;
6824 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6825 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6826 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6828 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6832 blobs = g_new0 (char *, sig->param_count);
6833 types = g_new0 (guint32, sig->param_count);
6834 get_default_param_value_blobs (method, blobs, types);
6837 /* Build MonoType for the type from the Constant Table */
6839 type = g_new0 (MonoType, 1);
6840 type->type = types [i];
6841 type->data.klass = NULL;
6842 if (types [i] == MONO_TYPE_CLASS)
6843 type->data.klass = mono_defaults.object_class;
6844 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6845 /* For enums, types [i] contains the base type */
6847 type->type = MONO_TYPE_VALUETYPE;
6848 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6850 type->data.klass = mono_class_from_mono_type (type);
6852 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6854 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6855 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6856 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6857 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6859 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6865 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6867 mono_array_setref (res, i, param);
6874 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6876 mono_metadata_free_marshal_spec (mspecs [i]);
6879 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6883 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6885 return mono_param_get_objects_internal (domain, method, NULL);
6889 * mono_method_body_get_object:
6890 * @domain: an app domain
6893 * Return an System.Reflection.MethodBody object representing the method @method.
6895 MonoReflectionMethodBody*
6896 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6898 static MonoClass *System_Reflection_MethodBody = NULL;
6899 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6900 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6901 MonoReflectionMethodBody *ret;
6902 MonoMethodHeader *header;
6904 guint32 method_rva, local_var_sig_token;
6906 unsigned char format, flags;
6909 /* for compatibility with .net */
6910 if (method->dynamic)
6911 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6913 if (!System_Reflection_MethodBody)
6914 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6915 if (!System_Reflection_LocalVariableInfo)
6916 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6917 if (!System_Reflection_ExceptionHandlingClause)
6918 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6920 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6922 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6923 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6924 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6925 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6928 image = method->klass->image;
6929 header = mono_method_get_header (method);
6931 if (!image->dynamic) {
6932 /* Obtain local vars signature token */
6933 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6934 ptr = mono_image_rva_map (image, method_rva);
6935 flags = *(const unsigned char *) ptr;
6936 format = flags & METHOD_HEADER_FORMAT_MASK;
6938 case METHOD_HEADER_TINY_FORMAT:
6939 local_var_sig_token = 0;
6941 case METHOD_HEADER_FAT_FORMAT:
6945 local_var_sig_token = read32 (ptr);
6948 g_assert_not_reached ();
6951 local_var_sig_token = 0; //FIXME
6953 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6955 ret->init_locals = header->init_locals;
6956 ret->max_stack = header->max_stack;
6957 ret->local_var_sig_token = local_var_sig_token;
6958 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6959 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6962 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6963 for (i = 0; i < header->num_locals; ++i) {
6964 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6965 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6966 info->is_pinned = header->locals [i]->pinned;
6967 info->local_index = i;
6968 mono_array_setref (ret->locals, i, info);
6972 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6973 for (i = 0; i < header->num_clauses; ++i) {
6974 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6975 MonoExceptionClause *clause = &header->clauses [i];
6977 info->flags = clause->flags;
6978 info->try_offset = clause->try_offset;
6979 info->try_length = clause->try_len;
6980 info->handler_offset = clause->handler_offset;
6981 info->handler_length = clause->handler_len;
6982 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6983 info->filter_offset = clause->data.filter_offset;
6984 else if (clause->data.catch_class)
6985 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6987 mono_array_setref (ret->clauses, i, info);
6990 mono_metadata_free_mh (header);
6991 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6996 * mono_get_dbnull_object:
6997 * @domain: Domain where the object lives
6999 * Returns the System.DBNull.Value singleton object
7001 * Used as the value for ParameterInfo.DefaultValue
7004 mono_get_dbnull_object (MonoDomain *domain)
7007 static MonoClassField *dbnull_value_field = NULL;
7009 if (!dbnull_value_field) {
7010 MonoClass *dbnull_klass;
7011 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7012 mono_class_init (dbnull_klass);
7013 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7014 g_assert (dbnull_value_field);
7016 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7022 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7024 guint32 param_index, i, lastp, crow = 0;
7025 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7028 MonoClass *klass = method->klass;
7029 MonoImage *image = klass->image;
7030 MonoMethodSignature *methodsig = mono_method_signature (method);
7032 MonoTableInfo *constt;
7033 MonoTableInfo *methodt;
7034 MonoTableInfo *paramt;
7036 if (!methodsig->param_count)
7039 mono_class_init (klass);
7041 if (klass->image->dynamic) {
7042 MonoReflectionMethodAux *aux;
7043 if (method->is_inflated)
7044 method = ((MonoMethodInflated*)method)->declaring;
7045 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7046 if (aux && aux->param_defaults) {
7047 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7048 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7053 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7054 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7055 constt = &image->tables [MONO_TABLE_CONSTANT];
7057 idx = mono_method_get_index (method) - 1;
7058 g_assert (idx != -1);
7060 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7061 if (idx + 1 < methodt->rows)
7062 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7064 lastp = paramt->rows + 1;
7066 for (i = param_index; i < lastp; ++i) {
7069 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7070 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7072 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7075 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7080 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7081 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7082 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7089 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7094 MonoType *basetype = type;
7099 klass = mono_class_from_mono_type (type);
7100 if (klass->valuetype) {
7101 object = mono_object_new (domain, klass);
7102 retval = ((gchar *) object + sizeof (MonoObject));
7103 if (klass->enumtype)
7104 basetype = mono_class_enum_basetype (klass);
7109 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7116 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7119 gboolean quoted = FALSE;
7121 memset (assembly, 0, sizeof (MonoAssemblyName));
7122 assembly->culture = "";
7123 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7130 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7141 /* Remove trailing whitespace */
7143 while (*s && g_ascii_isspace (*s))
7146 while (g_ascii_isspace (*p))
7149 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7151 assembly->major = strtoul (p, &s, 10);
7152 if (s == p || *s != '.')
7155 assembly->minor = strtoul (p, &s, 10);
7156 if (s == p || *s != '.')
7159 assembly->build = strtoul (p, &s, 10);
7160 if (s == p || *s != '.')
7163 assembly->revision = strtoul (p, &s, 10);
7167 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7169 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7170 assembly->culture = "";
7173 assembly->culture = p;
7174 while (*p && *p != ',') {
7178 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7180 if (strncmp (p, "null", 4) == 0) {
7185 while (*p && *p != ',') {
7188 len = (p - start + 1);
7189 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7190 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7191 g_strlcpy ((char*)assembly->public_key_token, start, len);
7194 while (*p && *p != ',')
7198 while (g_ascii_isspace (*p) || *p == ',') {
7212 * mono_reflection_parse_type:
7215 * Parse a type name as accepted by the GetType () method and output the info
7216 * extracted in the info structure.
7217 * the name param will be mangled, so, make a copy before passing it to this function.
7218 * The fields in info will be valid until the memory pointed to by name is valid.
7220 * See also mono_type_get_name () below.
7222 * Returns: 0 on parse error.
7225 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7226 MonoTypeNameParse *info)
7228 char *start, *p, *w, *temp, *last_point, *startn;
7229 int in_modifiers = 0;
7230 int isbyref = 0, rank, arity = 0, i;
7232 start = p = w = name;
7234 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7235 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7236 info->name = info->name_space = NULL;
7237 info->nested = NULL;
7238 info->modifiers = NULL;
7239 info->type_arguments = NULL;
7241 /* last_point separates the namespace from the name */
7244 while (*p == ' ') p++, start++, w++, name++;
7249 *p = 0; /* NULL terminate the name */
7251 info->nested = g_list_append (info->nested, startn);
7252 /* we have parsed the nesting namespace + name */
7256 info->name_space = start;
7258 info->name = last_point + 1;
7260 info->name_space = (char *)"";
7279 i = strtol (p, &temp, 10);
7296 info->name_space = start;
7298 info->name = last_point + 1;
7300 info->name_space = (char *)"";
7307 if (isbyref) /* only one level allowed by the spec */
7310 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7314 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7320 info->type_arguments = g_ptr_array_new ();
7321 for (i = 0; i < arity; i++) {
7322 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7323 gboolean fqname = FALSE;
7325 g_ptr_array_add (info->type_arguments, subinfo);
7332 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7335 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7336 if (fqname && (*p != ']')) {
7344 while (*p && (*p != ']'))
7352 if (g_ascii_isspace (*aname)) {
7359 !assembly_name_to_aname (&subinfo->assembly, aname))
7361 } else if (fqname && (*p == ']')) {
7365 if (i + 1 < arity) {
7385 else if (*p == '*') /* '*' means unknown lower bound */
7386 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7393 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7404 if (g_ascii_isspace (*p)) {
7411 return 0; /* missing assembly name */
7412 if (!assembly_name_to_aname (&info->assembly, p))
7418 if (info->assembly.name)
7421 // *w = 0; /* terminate class name */
7423 if (!info->name || !*info->name)
7427 /* add other consistency checks */
7432 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7434 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7438 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7440 gboolean type_resolve = FALSE;
7442 MonoImage *rootimage = image;
7444 if (info->assembly.name) {
7445 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7446 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7448 * This could happen in the AOT compiler case when the search hook is not
7451 assembly = image->assembly;
7453 /* then we must load the assembly ourselve - see #60439 */
7454 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7458 image = assembly->image;
7459 } else if (!image) {
7460 image = mono_defaults.corlib;
7463 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7465 image = mono_defaults.corlib;
7466 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7473 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7478 gboolean bounded = FALSE;
7481 image = mono_defaults.corlib;
7484 klass = mono_class_from_name_case (image, info->name_space, info->name);
7486 klass = mono_class_from_name (image, info->name_space, info->name);
7489 for (mod = info->nested; mod; mod = mod->next) {
7490 gpointer iter = NULL;
7494 mono_class_init (parent);
7496 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7498 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7501 if (strcmp (klass->name, mod->data) == 0)
7511 if (info->type_arguments) {
7512 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7513 MonoReflectionType *the_type;
7517 for (i = 0; i < info->type_arguments->len; i++) {
7518 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7520 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7521 if (!type_args [i]) {
7527 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7529 instance = mono_reflection_bind_generic_parameters (
7530 the_type, info->type_arguments->len, type_args);
7536 klass = mono_class_from_mono_type (instance);
7539 for (mod = info->modifiers; mod; mod = mod->next) {
7540 modval = GPOINTER_TO_UINT (mod->data);
7541 if (!modval) { /* byref: must be last modifier */
7542 return &klass->this_arg;
7543 } else if (modval == -1) {
7544 klass = mono_ptr_class_get (&klass->byval_arg);
7545 } else if (modval == -2) {
7547 } else { /* array rank */
7548 klass = mono_bounded_array_class_get (klass, modval, bounded);
7552 return &klass->byval_arg;
7556 * mono_reflection_get_type:
7557 * @image: a metadata context
7558 * @info: type description structure
7559 * @ignorecase: flag for case-insensitive string compares
7560 * @type_resolve: whenever type resolve was already tried
7562 * Build a MonoType from the type description in @info.
7567 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7568 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7572 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7574 MonoReflectionAssemblyBuilder *abuilder;
7578 g_assert (assembly->dynamic);
7579 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7581 /* Enumerate all modules */
7584 if (abuilder->modules) {
7585 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7586 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7587 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7593 if (!type && abuilder->loaded_modules) {
7594 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7595 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7596 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7606 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7609 MonoReflectionAssembly *assembly;
7613 if (image && image->dynamic)
7614 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7616 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7619 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7626 *type_resolve = TRUE;
7629 /* Reconstruct the type name */
7630 fullName = g_string_new ("");
7631 if (info->name_space && (info->name_space [0] != '\0'))
7632 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7634 g_string_printf (fullName, "%s", info->name);
7635 for (mod = info->nested; mod; mod = mod->next)
7636 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7638 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7640 if (assembly->assembly->dynamic)
7641 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7643 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7646 g_string_free (fullName, TRUE);
7651 mono_reflection_free_type_info (MonoTypeNameParse *info)
7653 g_list_free (info->modifiers);
7654 g_list_free (info->nested);
7656 if (info->type_arguments) {
7659 for (i = 0; i < info->type_arguments->len; i++) {
7660 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7662 mono_reflection_free_type_info (subinfo);
7663 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7667 g_ptr_array_free (info->type_arguments, TRUE);
7672 * mono_reflection_type_from_name:
7674 * @image: a metadata context (can be NULL).
7676 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7677 * it defaults to get the type from @image or, if @image is NULL or loading
7678 * from it fails, uses corlib.
7682 mono_reflection_type_from_name (char *name, MonoImage *image)
7684 MonoType *type = NULL;
7685 MonoTypeNameParse info;
7688 /* Make a copy since parse_type modifies its argument */
7689 tmp = g_strdup (name);
7691 /*g_print ("requested type %s\n", str);*/
7692 if (mono_reflection_parse_type (tmp, &info)) {
7693 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7697 mono_reflection_free_type_info (&info);
7702 * mono_reflection_get_token:
7704 * Return the metadata token of OBJ which should be an object
7705 * representing a metadata element.
7708 mono_reflection_get_token (MonoObject *obj)
7713 klass = obj->vtable->klass;
7715 if (strcmp (klass->name, "MethodBuilder") == 0) {
7716 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7718 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7719 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7720 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7722 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7723 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7724 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7726 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7727 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7728 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7729 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7730 } else if (strcmp (klass->name, "MonoType") == 0) {
7731 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7732 MonoClass *mc = mono_class_from_mono_type (type);
7733 if (!mono_class_init (mc))
7734 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7736 token = mc->type_token;
7737 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7738 strcmp (klass->name, "MonoMethod") == 0 ||
7739 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7740 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7741 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7742 if (m->method->is_inflated) {
7743 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7744 return inflated->declaring->token;
7746 token = m->method->token;
7748 } else if (strcmp (klass->name, "MonoField") == 0) {
7749 MonoReflectionField *f = (MonoReflectionField*)obj;
7751 if (is_field_on_inst (f->field)) {
7752 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7753 int field_index = f->field - dgclass->fields;
7756 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7757 obj = dgclass->field_objects [field_index];
7758 return mono_reflection_get_token (obj);
7760 token = mono_class_get_field_token (f->field);
7761 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7762 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7764 token = mono_class_get_property_token (p->property);
7765 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7766 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7768 token = mono_class_get_event_token (p->event);
7769 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7770 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7771 MonoClass *member_class = mono_object_class (p->MemberImpl);
7772 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7774 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7775 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7776 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7779 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7780 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7782 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7783 MonoException *ex = mono_get_exception_not_implemented (msg);
7785 mono_raise_exception (ex);
7792 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7794 int slen, type = t->type;
7795 MonoClass *tklass = t->data.klass;
7801 case MONO_TYPE_BOOLEAN: {
7802 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7807 case MONO_TYPE_CHAR:
7809 case MONO_TYPE_I2: {
7810 guint16 *val = g_malloc (sizeof (guint16));
7815 #if SIZEOF_VOID_P == 4
7821 case MONO_TYPE_I4: {
7822 guint32 *val = g_malloc (sizeof (guint32));
7827 #if SIZEOF_VOID_P == 8
7828 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7832 case MONO_TYPE_I8: {
7833 guint64 *val = g_malloc (sizeof (guint64));
7838 case MONO_TYPE_R8: {
7839 double *val = g_malloc (sizeof (double));
7844 case MONO_TYPE_VALUETYPE:
7845 if (t->data.klass->enumtype) {
7846 type = mono_class_enum_basetype (t->data.klass)->type;
7849 MonoClass *k = t->data.klass;
7851 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7852 guint64 *val = g_malloc (sizeof (guint64));
7858 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7861 case MONO_TYPE_STRING:
7862 if (*p == (char)0xFF) {
7866 slen = mono_metadata_decode_value (p, &p);
7868 return mono_string_new_len (mono_domain_get (), p, slen);
7869 case MONO_TYPE_CLASS: {
7872 if (*p == (char)0xFF) {
7877 slen = mono_metadata_decode_value (p, &p);
7878 n = g_memdup (p, slen + 1);
7880 t = mono_reflection_type_from_name (n, image);
7882 g_warning ("Cannot load type '%s'", n);
7886 return mono_type_get_object (mono_domain_get (), t);
7890 case MONO_TYPE_OBJECT: {
7893 MonoClass *subc = NULL;
7898 } else if (subt == 0x0E) {
7899 type = MONO_TYPE_STRING;
7901 } else if (subt == 0x1D) {
7902 MonoType simple_type = {{0}};
7906 type = MONO_TYPE_SZARRAY;
7907 if (etype == 0x50) {
7908 tklass = mono_defaults.systemtype_class;
7911 /* See Partition II, Appendix B3 */
7912 etype = MONO_TYPE_OBJECT;
7913 simple_type.type = etype;
7914 tklass = mono_class_from_mono_type (&simple_type);
7917 } else if (subt == 0x55) {
7920 slen = mono_metadata_decode_value (p, &p);
7921 n = g_memdup (p, slen + 1);
7923 t = mono_reflection_type_from_name (n, image);
7925 g_error ("Cannot load type '%s'", n);
7928 subc = mono_class_from_mono_type (t);
7929 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7930 MonoType simple_type = {{0}};
7931 simple_type.type = subt;
7932 subc = mono_class_from_mono_type (&simple_type);
7934 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7936 val = load_cattr_value (image, &subc->byval_arg, p, end);
7937 obj = mono_object_new (mono_domain_get (), subc);
7938 g_assert (!subc->has_references);
7939 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7943 case MONO_TYPE_SZARRAY: {
7945 guint32 i, alen, basetype;
7948 if (alen == 0xffffffff) {
7952 arr = mono_array_new (mono_domain_get(), tklass, alen);
7953 basetype = tklass->byval_arg.type;
7954 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7955 basetype = mono_class_enum_basetype (tklass)->type;
7960 case MONO_TYPE_BOOLEAN:
7961 for (i = 0; i < alen; i++) {
7962 MonoBoolean val = *p++;
7963 mono_array_set (arr, MonoBoolean, i, val);
7966 case MONO_TYPE_CHAR:
7969 for (i = 0; i < alen; i++) {
7970 guint16 val = read16 (p);
7971 mono_array_set (arr, guint16, i, val);
7978 for (i = 0; i < alen; i++) {
7979 guint32 val = read32 (p);
7980 mono_array_set (arr, guint32, i, val);
7985 for (i = 0; i < alen; i++) {
7988 mono_array_set (arr, double, i, val);
7994 for (i = 0; i < alen; i++) {
7995 guint64 val = read64 (p);
7996 mono_array_set (arr, guint64, i, val);
8000 case MONO_TYPE_CLASS:
8001 case MONO_TYPE_OBJECT:
8002 case MONO_TYPE_STRING:
8003 for (i = 0; i < alen; i++) {
8004 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8005 mono_array_setref (arr, i, item);
8009 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8015 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8021 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8023 static MonoClass *klass;
8024 static MonoMethod *ctor;
8026 void *params [2], *unboxed;
8029 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8031 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8033 params [0] = mono_type_get_object (mono_domain_get (), t);
8035 retval = mono_object_new (mono_domain_get (), klass);
8036 unboxed = mono_object_unbox (retval);
8037 mono_runtime_invoke (ctor, unboxed, params, NULL);
8043 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8045 static MonoClass *klass;
8046 static MonoMethod *ctor;
8048 void *unboxed, *params [2];
8051 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8053 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8056 params [1] = typedarg;
8057 retval = mono_object_new (mono_domain_get (), klass);
8058 unboxed = mono_object_unbox (retval);
8059 mono_runtime_invoke (ctor, unboxed, params, NULL);
8065 type_is_reference (MonoType *type)
8067 switch (type->type) {
8068 case MONO_TYPE_BOOLEAN:
8069 case MONO_TYPE_CHAR:
8082 case MONO_TYPE_VALUETYPE:
8090 free_param_data (MonoMethodSignature *sig, void **params) {
8092 for (i = 0; i < sig->param_count; ++i) {
8093 if (!type_is_reference (sig->params [i]))
8094 g_free (params [i]);
8099 * Find the field index in the metadata FieldDef table.
8102 find_field_index (MonoClass *klass, MonoClassField *field) {
8105 for (i = 0; i < klass->field.count; ++i) {
8106 if (field == &klass->fields [i])
8107 return klass->field.first + 1 + i;
8113 * Find the property index in the metadata Property table.
8116 find_property_index (MonoClass *klass, MonoProperty *property) {
8119 for (i = 0; i < klass->ext->property.count; ++i) {
8120 if (property == &klass->ext->properties [i])
8121 return klass->ext->property.first + 1 + i;
8127 * Find the event index in the metadata Event table.
8130 find_event_index (MonoClass *klass, MonoEvent *event) {
8133 for (i = 0; i < klass->ext->event.count; ++i) {
8134 if (event == &klass->ext->events [i])
8135 return klass->ext->event.first + 1 + i;
8141 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8143 const char *p = (const char*)data;
8145 guint32 i, j, num_named;
8147 void *params_buf [32];
8149 MonoMethodSignature *sig;
8151 mono_error_init (error);
8153 mono_class_init (method->klass);
8155 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8156 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8161 attr = mono_object_new (mono_domain_get (), method->klass);
8162 mono_runtime_invoke (method, attr, NULL, NULL);
8166 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8169 /*g_print ("got attr %s\n", method->klass->name);*/
8171 sig = mono_method_signature (method);
8172 if (sig->param_count < 32)
8173 params = params_buf;
8175 /* Allocate using GC so it gets GC tracking */
8176 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8180 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8181 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8185 attr = mono_object_new (mono_domain_get (), method->klass);
8186 mono_runtime_invoke (method, attr, params, NULL);
8187 free_param_data (method->signature, params);
8188 num_named = read16 (named);
8190 for (j = 0; j < num_named; j++) {
8192 char *name, named_type, data_type;
8193 named_type = *named++;
8194 data_type = *named++; /* type of data */
8195 if (data_type == MONO_TYPE_SZARRAY)
8196 data_type = *named++;
8197 if (data_type == MONO_TYPE_ENUM) {
8200 type_len = mono_metadata_decode_blob_size (named, &named);
8201 type_name = g_malloc (type_len + 1);
8202 memcpy (type_name, named, type_len);
8203 type_name [type_len] = 0;
8205 /* FIXME: lookup the type and check type consistency */
8208 name_len = mono_metadata_decode_blob_size (named, &named);
8209 name = g_malloc (name_len + 1);
8210 memcpy (name, named, name_len);
8211 name [name_len] = 0;
8213 if (named_type == 0x53) {
8214 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8215 void *val = load_cattr_value (image, field->type, named, &named);
8216 mono_field_set_value (attr, field, val);
8217 if (!type_is_reference (field->type))
8219 } else if (named_type == 0x54) {
8222 MonoType *prop_type;
8224 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8225 /* can we have more that 1 arg in a custom attr named property? */
8226 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8227 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8228 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8229 mono_property_set_value (prop, attr, pparams, NULL);
8230 if (!type_is_reference (prop_type))
8231 g_free (pparams [0]);
8236 if (params != params_buf)
8237 mono_gc_free_fixed (params);
8243 * mono_reflection_create_custom_attr_data_args:
8245 * Create an array of typed and named arguments from the cattr blob given by DATA.
8246 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8247 * NAMED_ARG_INFO will contain information about the named arguments.
8250 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)
8252 MonoArray *typedargs, *namedargs;
8253 MonoClass *attrklass;
8255 const char *p = (const char*)data;
8257 guint32 i, j, num_named;
8258 CattrNamedArg *arginfo = NULL;
8260 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8263 mono_class_init (method->klass);
8267 *named_arg_info = NULL;
8269 domain = mono_domain_get ();
8271 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8274 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8278 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8282 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8283 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8284 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8285 mono_array_setref (typedargs, i, obj);
8287 if (!type_is_reference (mono_method_signature (method)->params [i]))
8292 num_named = read16 (named);
8293 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8295 attrklass = method->klass;
8297 arginfo = g_new0 (CattrNamedArg, num_named);
8298 *named_arg_info = arginfo;
8300 for (j = 0; j < num_named; j++) {
8302 char *name, named_type, data_type;
8303 named_type = *named++;
8304 data_type = *named++; /* type of data */
8305 if (data_type == MONO_TYPE_SZARRAY)
8306 data_type = *named++;
8307 if (data_type == MONO_TYPE_ENUM) {
8310 type_len = mono_metadata_decode_blob_size (named, &named);
8311 type_name = g_malloc (type_len + 1);
8312 memcpy (type_name, named, type_len);
8313 type_name [type_len] = 0;
8315 /* FIXME: lookup the type and check type consistency */
8318 name_len = mono_metadata_decode_blob_size (named, &named);
8319 name = g_malloc (name_len + 1);
8320 memcpy (name, named, name_len);
8321 name [name_len] = 0;
8323 if (named_type == 0x53) {
8325 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8328 arginfo [j].type = field->type;
8329 arginfo [j].field = field;
8331 val = load_cattr_value (image, field->type, named, &named);
8332 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8333 mono_array_setref (namedargs, j, obj);
8334 if (!type_is_reference (field->type))
8336 } else if (named_type == 0x54) {
8338 MonoType *prop_type;
8339 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8342 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8343 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8345 arginfo [j].type = prop_type;
8346 arginfo [j].prop = prop;
8348 val = load_cattr_value (image, prop_type, named, &named);
8349 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8350 mono_array_setref (namedargs, j, obj);
8351 if (!type_is_reference (prop_type))
8357 *typed_args = typedargs;
8358 *named_args = namedargs;
8362 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8365 MonoArray *typedargs, *namedargs;
8368 CattrNamedArg *arginfo;
8377 image = assembly->assembly->image;
8378 method = ref_method->method;
8379 domain = mono_object_domain (ref_method);
8381 if (!mono_class_init (method->klass))
8382 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8384 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8385 if (mono_loader_get_last_error ())
8386 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8388 if (!typedargs || !namedargs)
8391 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8392 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8393 MonoObject *typedarg;
8395 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8396 mono_array_setref (typedargs, i, typedarg);
8399 for (i = 0; i < mono_array_length (namedargs); ++i) {
8400 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8401 MonoObject *typedarg, *namedarg, *minfo;
8403 if (arginfo [i].prop)
8404 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8406 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8408 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8409 namedarg = create_cattr_named_arg (minfo, typedarg);
8411 mono_array_setref (namedargs, i, namedarg);
8414 *ctor_args = typedargs;
8415 *named_args = namedargs;
8419 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8421 static MonoMethod *ctor;
8426 g_assert (image->assembly);
8429 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8431 domain = mono_domain_get ();
8432 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8433 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8434 params [1] = mono_assembly_get_object (domain, image->assembly);
8435 params [2] = (gpointer)&cattr->data;
8436 params [3] = &cattr->data_size;
8437 mono_runtime_invoke (ctor, attr, params, NULL);
8442 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8448 mono_error_init (error);
8451 for (i = 0; i < cinfo->num_attrs; ++i) {
8452 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8456 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8458 for (i = 0; i < cinfo->num_attrs; ++i) {
8459 if (!cinfo->attrs [i].ctor)
8460 /* The cattr type is not finished yet */
8461 /* We should include the type name but cinfo doesn't contain it */
8462 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8463 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8464 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8465 if (!mono_error_ok (error))
8467 mono_array_setref (result, n, attr);
8475 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8479 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8483 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8489 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8490 for (i = 0; i < cinfo->num_attrs; ++i) {
8491 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8492 mono_array_setref (result, i, attr);
8498 * mono_custom_attrs_from_index:
8500 * Returns: NULL if no attributes are found or if a loading error occurs.
8503 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8505 guint32 mtoken, i, len;
8506 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8508 MonoCustomAttrInfo *ainfo;
8509 GList *tmp, *list = NULL;
8512 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8514 i = mono_metadata_custom_attrs_from_index (image, idx);
8518 while (i < ca->rows) {
8519 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8521 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8524 len = g_list_length (list);
8527 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8528 ainfo->num_attrs = len;
8529 ainfo->image = image;
8530 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8531 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8532 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8533 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8534 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8535 mtoken |= MONO_TOKEN_METHOD_DEF;
8537 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8538 mtoken |= MONO_TOKEN_MEMBER_REF;
8541 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8544 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8545 if (!ainfo->attrs [i].ctor) {
8546 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8552 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8553 /*FIXME raising an exception here doesn't make any sense*/
8554 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8559 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8560 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8561 ainfo->attrs [i].data = (guchar*)data;
8569 mono_custom_attrs_from_method (MonoMethod *method)
8574 * An instantiated method has the same cattrs as the generic method definition.
8576 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8577 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8579 if (method->is_inflated)
8580 method = ((MonoMethodInflated *) method)->declaring;
8582 if (method->dynamic || method->klass->image->dynamic)
8583 return lookup_custom_attr (method->klass->image, method);
8586 /* Synthetic methods */
8589 idx = mono_method_get_index (method);
8590 idx <<= MONO_CUSTOM_ATTR_BITS;
8591 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8592 return mono_custom_attrs_from_index (method->klass->image, idx);
8596 mono_custom_attrs_from_class (MonoClass *klass)
8600 if (klass->generic_class)
8601 klass = klass->generic_class->container_class;
8603 if (klass->image->dynamic)
8604 return lookup_custom_attr (klass->image, klass);
8606 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8607 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8608 idx <<= MONO_CUSTOM_ATTR_BITS;
8609 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8611 idx = mono_metadata_token_index (klass->type_token);
8612 idx <<= MONO_CUSTOM_ATTR_BITS;
8613 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8615 return mono_custom_attrs_from_index (klass->image, idx);
8619 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8623 if (assembly->image->dynamic)
8624 return lookup_custom_attr (assembly->image, assembly);
8625 idx = 1; /* there is only one assembly */
8626 idx <<= MONO_CUSTOM_ATTR_BITS;
8627 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8628 return mono_custom_attrs_from_index (assembly->image, idx);
8631 static MonoCustomAttrInfo*
8632 mono_custom_attrs_from_module (MonoImage *image)
8637 return lookup_custom_attr (image, image);
8638 idx = 1; /* there is only one module */
8639 idx <<= MONO_CUSTOM_ATTR_BITS;
8640 idx |= MONO_CUSTOM_ATTR_MODULE;
8641 return mono_custom_attrs_from_index (image, idx);
8645 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8649 if (klass->image->dynamic) {
8650 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8651 return lookup_custom_attr (klass->image, property);
8653 idx = find_property_index (klass, property);
8654 idx <<= MONO_CUSTOM_ATTR_BITS;
8655 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8656 return mono_custom_attrs_from_index (klass->image, idx);
8660 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8664 if (klass->image->dynamic) {
8665 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8666 return lookup_custom_attr (klass->image, event);
8668 idx = find_event_index (klass, event);
8669 idx <<= MONO_CUSTOM_ATTR_BITS;
8670 idx |= MONO_CUSTOM_ATTR_EVENT;
8671 return mono_custom_attrs_from_index (klass->image, idx);
8675 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8678 if (klass->image->dynamic) {
8679 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8680 return lookup_custom_attr (klass->image, field);
8682 idx = find_field_index (klass, field);
8683 idx <<= MONO_CUSTOM_ATTR_BITS;
8684 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8685 return mono_custom_attrs_from_index (klass->image, idx);
8689 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8692 guint32 i, idx, method_index;
8693 guint32 param_list, param_last, param_pos, found;
8695 MonoReflectionMethodAux *aux;
8698 * An instantiated method has the same cattrs as the generic method definition.
8700 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8701 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8703 if (method->is_inflated)
8704 method = ((MonoMethodInflated *) method)->declaring;
8706 if (method->klass->image->dynamic) {
8707 MonoCustomAttrInfo *res, *ainfo;
8710 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8711 if (!aux || !aux->param_cattr)
8714 /* Need to copy since it will be freed later */
8715 ainfo = aux->param_cattr [param];
8718 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8719 res = g_malloc0 (size);
8720 memcpy (res, ainfo, size);
8724 image = method->klass->image;
8725 method_index = mono_method_get_index (method);
8728 ca = &image->tables [MONO_TABLE_METHOD];
8730 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8731 if (method_index == ca->rows) {
8732 ca = &image->tables [MONO_TABLE_PARAM];
8733 param_last = ca->rows + 1;
8735 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8736 ca = &image->tables [MONO_TABLE_PARAM];
8739 for (i = param_list; i < param_last; ++i) {
8740 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8741 if (param_pos == param) {
8749 idx <<= MONO_CUSTOM_ATTR_BITS;
8750 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8751 return mono_custom_attrs_from_index (image, idx);
8755 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8759 for (i = 0; i < ainfo->num_attrs; ++i) {
8760 klass = ainfo->attrs [i].ctor->klass;
8761 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8768 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8775 for (i = 0; i < ainfo->num_attrs; ++i) {
8776 klass = ainfo->attrs [i].ctor->klass;
8777 if (mono_class_has_parent (klass, attr_klass)) {
8782 if (attr_index == -1)
8785 attrs = mono_custom_attrs_construct (ainfo);
8787 return mono_array_get (attrs, MonoObject*, attr_index);
8793 * mono_reflection_get_custom_attrs_info:
8794 * @obj: a reflection object handle
8796 * Return the custom attribute info for attributes defined for the
8797 * reflection handle @obj. The objects.
8799 * FIXME this function leaks like a sieve for SRE objects.
8802 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8805 MonoCustomAttrInfo *cinfo = NULL;
8807 klass = obj->vtable->klass;
8808 if (klass == mono_defaults.monotype_class) {
8809 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8810 klass = mono_class_from_mono_type (type);
8811 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8812 cinfo = mono_custom_attrs_from_class (klass);
8813 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8814 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8815 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8816 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8817 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8818 cinfo = mono_custom_attrs_from_module (module->image);
8819 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8820 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8821 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8822 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8823 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8824 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8825 } else if (strcmp ("MonoField", klass->name) == 0) {
8826 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8827 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8828 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8829 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8830 cinfo = mono_custom_attrs_from_method (rmethod->method);
8831 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8832 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8833 cinfo = mono_custom_attrs_from_method (rmethod->method);
8834 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8835 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8836 MonoClass *member_class = mono_object_class (param->MemberImpl);
8837 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8838 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8839 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8840 } else if (is_sr_mono_property (member_class)) {
8841 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8843 if (!(method = prop->property->get))
8844 method = prop->property->set;
8847 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8849 #ifndef DISABLE_REFLECTION_EMIT
8850 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8851 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8852 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8853 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8854 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8855 MonoMethod *method = NULL;
8856 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8857 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8858 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8859 method = ((MonoReflectionMethod *)c->cb)->method;
8861 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));
8863 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8867 char *type_name = mono_type_get_full_name (member_class);
8868 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8869 MonoException *ex = mono_get_exception_not_supported (msg);
8872 mono_raise_exception (ex);
8874 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8875 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8876 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8877 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8878 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8879 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8880 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8881 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8882 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8883 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8884 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8885 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8886 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8887 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8888 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8889 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8890 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8891 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8892 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8893 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8894 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8895 } else { /* handle other types here... */
8896 g_error ("get custom attrs not yet supported for %s", klass->name);
8903 * mono_reflection_get_custom_attrs_by_type:
8904 * @obj: a reflection object handle
8906 * Return an array with all the custom attributes defined of the
8907 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8908 * of that type are returned. The objects are fully build. Return NULL if a loading error
8912 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8915 MonoCustomAttrInfo *cinfo;
8917 mono_error_init (error);
8919 cinfo = mono_reflection_get_custom_attrs_info (obj);
8921 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8923 mono_custom_attrs_free (cinfo);
8925 if (mono_loader_get_last_error ())
8927 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8934 * mono_reflection_get_custom_attrs:
8935 * @obj: a reflection object handle
8937 * Return an array with all the custom attributes defined of the
8938 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8942 mono_reflection_get_custom_attrs (MonoObject *obj)
8946 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8950 * mono_reflection_get_custom_attrs_data:
8951 * @obj: a reflection obj handle
8953 * Returns an array of System.Reflection.CustomAttributeData,
8954 * which include information about attributes reflected on
8955 * types loaded using the Reflection Only methods
8958 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8961 MonoCustomAttrInfo *cinfo;
8963 cinfo = mono_reflection_get_custom_attrs_info (obj);
8965 result = mono_custom_attrs_data_construct (cinfo);
8967 mono_custom_attrs_free (cinfo);
8969 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8974 static MonoReflectionType*
8975 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8977 static MonoMethod *method_get_underlying_system_type = NULL;
8978 MonoMethod *usertype_method;
8980 if (!method_get_underlying_system_type)
8981 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8982 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8983 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8988 is_corlib_type (MonoClass *class)
8990 return class->image == mono_defaults.corlib;
8993 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8994 static MonoClass *cached_class; \
8996 return cached_class == _class; \
8997 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8998 cached_class = _class; \
9005 #ifndef DISABLE_REFLECTION_EMIT
9007 is_sre_array (MonoClass *class)
9009 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9013 is_sre_byref (MonoClass *class)
9015 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9019 is_sre_pointer (MonoClass *class)
9021 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9025 is_sre_generic_instance (MonoClass *class)
9027 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9031 is_sre_type_builder (MonoClass *class)
9033 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9037 is_sre_method_builder (MonoClass *class)
9039 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9043 is_sre_ctor_builder (MonoClass *class)
9045 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9049 is_sre_field_builder (MonoClass *class)
9051 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9055 is_sre_method_on_tb_inst (MonoClass *class)
9057 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9061 is_sre_ctor_on_tb_inst (MonoClass *class)
9063 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9067 mono_reflection_type_get_handle (MonoReflectionType* ref)
9075 if (is_usertype (ref)) {
9076 ref = mono_reflection_type_get_underlying_system_type (ref);
9077 if (ref == NULL || is_usertype (ref))
9083 class = mono_object_class (ref);
9085 if (is_sre_array (class)) {
9087 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9088 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9090 if (sre_array->rank == 0) //single dimentional array
9091 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9093 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9094 sre_array->type.type = res;
9096 } else if (is_sre_byref (class)) {
9098 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9099 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9101 res = &mono_class_from_mono_type (base)->this_arg;
9102 sre_byref->type.type = res;
9104 } else if (is_sre_pointer (class)) {
9106 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9107 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9109 res = &mono_ptr_class_get (base)->byval_arg;
9110 sre_pointer->type.type = res;
9112 } else if (is_sre_generic_instance (class)) {
9113 MonoType *res, **types;
9114 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9117 count = mono_array_length (gclass->type_arguments);
9118 types = g_new0 (MonoType*, count);
9119 for (i = 0; i < count; ++i) {
9120 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9121 types [i] = mono_reflection_type_get_handle (t);
9128 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9131 gclass->type.type = res;
9135 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9142 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9144 mono_reflection_type_get_handle (type);
9148 mono_reflection_register_with_runtime (MonoReflectionType *type)
9150 MonoType *res = mono_reflection_type_get_handle (type);
9151 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9155 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9157 class = mono_class_from_mono_type (res);
9159 mono_loader_lock (); /*same locking as mono_type_get_object*/
9160 mono_domain_lock (domain);
9162 if (!class->image->dynamic) {
9163 mono_class_setup_supertypes (class);
9165 if (!domain->type_hash)
9166 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9167 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9168 mono_g_hash_table_insert (domain->type_hash, res, type);
9170 mono_domain_unlock (domain);
9171 mono_loader_unlock ();
9175 * LOCKING: Assumes the loader lock is held.
9177 static MonoMethodSignature*
9178 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9179 MonoMethodSignature *sig;
9182 count = parameters? mono_array_length (parameters): 0;
9184 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9185 sig->param_count = count;
9186 sig->sentinelpos = -1; /* FIXME */
9187 for (i = 0; i < count; ++i)
9188 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9193 * LOCKING: Assumes the loader lock is held.
9195 static MonoMethodSignature*
9196 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9197 MonoMethodSignature *sig;
9199 sig = parameters_to_signature (image, ctor->parameters);
9200 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9201 sig->ret = &mono_defaults.void_class->byval_arg;
9206 * LOCKING: Assumes the loader lock is held.
9208 static MonoMethodSignature*
9209 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9210 MonoMethodSignature *sig;
9212 sig = parameters_to_signature (image, method->parameters);
9213 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9214 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9215 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9219 static MonoMethodSignature*
9220 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9221 MonoMethodSignature *sig;
9223 sig = parameters_to_signature (NULL, method->parameters);
9224 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9225 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9226 sig->generic_param_count = 0;
9231 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9233 MonoClass *klass = mono_object_class (prop);
9234 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9235 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9236 *name = mono_string_to_utf8 (pb->name);
9237 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9239 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9240 *name = g_strdup (p->property->name);
9241 if (p->property->get)
9242 *type = mono_method_signature (p->property->get)->ret;
9244 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9249 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9251 MonoClass *klass = mono_object_class (field);
9252 if (strcmp (klass->name, "FieldBuilder") == 0) {
9253 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9254 *name = mono_string_to_utf8 (fb->name);
9255 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9257 MonoReflectionField *f = (MonoReflectionField *)field;
9258 *name = g_strdup (mono_field_get_name (f->field));
9259 *type = f->field->type;
9263 #else /* DISABLE_REFLECTION_EMIT */
9266 mono_reflection_register_with_runtime (MonoReflectionType *type)
9272 is_sre_type_builder (MonoClass *class)
9278 is_sre_generic_instance (MonoClass *class)
9284 init_type_builder_generics (MonoObject *type)
9288 #endif /* !DISABLE_REFLECTION_EMIT */
9292 is_sr_mono_field (MonoClass *class)
9294 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9298 is_sr_mono_property (MonoClass *class)
9300 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9304 is_sr_mono_method (MonoClass *class)
9306 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9310 is_sr_mono_cmethod (MonoClass *class)
9312 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9316 is_sr_mono_generic_method (MonoClass *class)
9318 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9322 is_sr_mono_generic_cmethod (MonoClass *class)
9324 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9328 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9330 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9334 is_usertype (MonoReflectionType *ref)
9336 MonoClass *class = mono_object_class (ref);
9337 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9340 static MonoReflectionType*
9341 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9343 if (!type || type->type)
9346 if (is_usertype (type)) {
9347 type = mono_reflection_type_get_underlying_system_type (type);
9348 if (is_usertype (type))
9349 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9355 * Encode a value in a custom attribute stream of bytes.
9356 * The value to encode is either supplied as an object in argument val
9357 * (valuetypes are boxed), or as a pointer to the data in the
9359 * @type represents the type of the value
9360 * @buffer is the start of the buffer
9361 * @p the current position in the buffer
9362 * @buflen contains the size of the buffer and is used to return the new buffer size
9363 * if this needs to be realloced.
9364 * @retbuffer and @retp return the start and the position of the buffer
9367 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9369 MonoTypeEnum simple_type;
9371 if ((p-buffer) + 10 >= *buflen) {
9374 newbuf = g_realloc (buffer, *buflen);
9375 p = newbuf + (p-buffer);
9379 argval = ((char*)arg + sizeof (MonoObject));
9380 simple_type = type->type;
9382 switch (simple_type) {
9383 case MONO_TYPE_BOOLEAN:
9388 case MONO_TYPE_CHAR:
9391 swap_with_size (p, argval, 2, 1);
9397 swap_with_size (p, argval, 4, 1);
9401 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9411 swap_with_size (p, argval, 8, 1);
9417 swap_with_size (p, argval, 8, 1);
9420 case MONO_TYPE_VALUETYPE:
9421 if (type->data.klass->enumtype) {
9422 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9425 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9428 case MONO_TYPE_STRING: {
9435 str = mono_string_to_utf8 ((MonoString*)arg);
9436 slen = strlen (str);
9437 if ((p-buffer) + 10 + slen >= *buflen) {
9441 newbuf = g_realloc (buffer, *buflen);
9442 p = newbuf + (p-buffer);
9445 mono_metadata_encode_value (slen, p, &p);
9446 memcpy (p, str, slen);
9451 case MONO_TYPE_CLASS: {
9459 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9460 slen = strlen (str);
9461 if ((p-buffer) + 10 + slen >= *buflen) {
9465 newbuf = g_realloc (buffer, *buflen);
9466 p = newbuf + (p-buffer);
9469 mono_metadata_encode_value (slen, p, &p);
9470 memcpy (p, str, slen);
9475 case MONO_TYPE_SZARRAY: {
9477 MonoClass *eclass, *arg_eclass;
9480 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9483 len = mono_array_length ((MonoArray*)arg);
9485 *p++ = (len >> 8) & 0xff;
9486 *p++ = (len >> 16) & 0xff;
9487 *p++ = (len >> 24) & 0xff;
9489 *retbuffer = buffer;
9490 eclass = type->data.klass;
9491 arg_eclass = mono_object_class (arg)->element_class;
9494 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9495 eclass = mono_defaults.object_class;
9497 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9498 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9499 int elsize = mono_class_array_element_size (arg_eclass);
9500 for (i = 0; i < len; ++i) {
9501 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9504 } else if (eclass->valuetype && arg_eclass->valuetype) {
9505 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9506 int elsize = mono_class_array_element_size (eclass);
9507 for (i = 0; i < len; ++i) {
9508 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9512 for (i = 0; i < len; ++i) {
9513 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9518 case MONO_TYPE_OBJECT: {
9524 * The parameter type is 'object' but the type of the actual
9525 * argument is not. So we have to add type information to the blob
9526 * too. This is completely undocumented in the spec.
9530 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9535 klass = mono_object_class (arg);
9537 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9540 } else if (klass->enumtype) {
9542 } else if (klass == mono_defaults.string_class) {
9543 simple_type = MONO_TYPE_STRING;
9546 } else if (klass->rank == 1) {
9548 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9549 /* See Partition II, Appendix B3 */
9552 *p++ = klass->element_class->byval_arg.type;
9553 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9555 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9556 *p++ = simple_type = klass->byval_arg.type;
9559 g_error ("unhandled type in custom attr");
9561 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9562 slen = strlen (str);
9563 if ((p-buffer) + 10 + slen >= *buflen) {
9567 newbuf = g_realloc (buffer, *buflen);
9568 p = newbuf + (p-buffer);
9571 mono_metadata_encode_value (slen, p, &p);
9572 memcpy (p, str, slen);
9575 simple_type = mono_class_enum_basetype (klass)->type;
9579 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9582 *retbuffer = buffer;
9586 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9588 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9589 char *str = type_get_qualified_name (type, NULL);
9590 int slen = strlen (str);
9594 * This seems to be optional...
9597 mono_metadata_encode_value (slen, p, &p);
9598 memcpy (p, str, slen);
9601 } else if (type->type == MONO_TYPE_OBJECT) {
9603 } else if (type->type == MONO_TYPE_CLASS) {
9604 /* it should be a type: encode_cattr_value () has the check */
9607 mono_metadata_encode_value (type->type, p, &p);
9608 if (type->type == MONO_TYPE_SZARRAY)
9609 /* See the examples in Partition VI, Annex B */
9610 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9616 #ifndef DISABLE_REFLECTION_EMIT
9618 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9621 /* Preallocate a large enough buffer */
9622 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9623 char *str = type_get_qualified_name (type, NULL);
9626 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9627 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9633 len += strlen (name);
9635 if ((p-buffer) + 20 + len >= *buflen) {
9639 newbuf = g_realloc (buffer, *buflen);
9640 p = newbuf + (p-buffer);
9644 encode_field_or_prop_type (type, p, &p);
9646 len = strlen (name);
9647 mono_metadata_encode_value (len, p, &p);
9648 memcpy (p, name, len);
9650 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9652 *retbuffer = buffer;
9656 * mono_reflection_get_custom_attrs_blob:
9657 * @ctor: custom attribute constructor
9658 * @ctorArgs: arguments o the constructor
9664 * Creates the blob of data that needs to be saved in the metadata and that represents
9665 * the custom attributed described by @ctor, @ctorArgs etc.
9666 * Returns: a Byte array representing the blob of data.
9669 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9672 MonoMethodSignature *sig;
9677 MONO_ARCH_SAVE_REGS;
9679 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9680 /* sig is freed later so allocate it in the heap */
9681 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9683 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9686 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9688 p = buffer = g_malloc (buflen);
9689 /* write the prolog */
9692 for (i = 0; i < sig->param_count; ++i) {
9693 arg = mono_array_get (ctorArgs, MonoObject*, i);
9694 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9698 i += mono_array_length (properties);
9700 i += mono_array_length (fields);
9702 *p++ = (i >> 8) & 0xff;
9705 for (i = 0; i < mono_array_length (properties); ++i) {
9709 prop = mono_array_get (properties, gpointer, i);
9710 get_prop_name_and_type (prop, &pname, &ptype);
9711 *p++ = 0x54; /* PROPERTY signature */
9712 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9719 for (i = 0; i < mono_array_length (fields); ++i) {
9723 field = mono_array_get (fields, gpointer, i);
9724 get_field_name_and_type (field, &fname, &ftype);
9725 *p++ = 0x53; /* FIELD signature */
9726 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9731 g_assert (p - buffer <= buflen);
9732 buflen = p - buffer;
9733 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9734 p = mono_array_addr (result, char, 0);
9735 memcpy (p, buffer, buflen);
9737 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9743 * mono_reflection_setup_internal_class:
9744 * @tb: a TypeBuilder object
9746 * Creates a MonoClass that represents the TypeBuilder.
9747 * This is a trick that lets us simplify a lot of reflection code
9748 * (and will allow us to support Build and Run assemblies easier).
9751 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9754 MonoClass *klass, *parent;
9756 MONO_ARCH_SAVE_REGS;
9758 RESOLVE_TYPE (tb->parent);
9760 mono_loader_lock ();
9763 /* check so we can compile corlib correctly */
9764 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9765 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9766 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9768 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9774 /* the type has already being created: it means we just have to change the parent */
9775 if (tb->type.type) {
9776 klass = mono_class_from_mono_type (tb->type.type);
9777 klass->parent = NULL;
9778 /* fool mono_class_setup_parent */
9779 klass->supertypes = NULL;
9780 mono_class_setup_parent (klass, parent);
9781 mono_class_setup_mono_type (klass);
9782 mono_loader_unlock ();
9786 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9788 klass->image = &tb->module->dynamic_image->image;
9790 klass->inited = 1; /* we lie to the runtime */
9791 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9792 if (!mono_error_ok (&error))
9794 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9795 if (!mono_error_ok (&error))
9797 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9798 klass->flags = tb->attrs;
9800 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9802 klass->element_class = klass;
9804 if (mono_class_get_ref_info (klass) == NULL) {
9806 mono_class_set_ref_info (klass, tb);
9808 /* Put into cache so mono_class_get () will find it.
9809 Skip nested types as those should not be available on the global scope. */
9810 if (!tb->nesting_type) {
9811 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9813 klass->image->reflection_info_unregister_classes =
9814 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9817 g_assert (mono_class_get_ref_info (klass) == tb);
9820 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9821 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9823 if (parent != NULL) {
9824 mono_class_setup_parent (klass, parent);
9825 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9826 const char *old_n = klass->name;
9827 /* trick to get relative numbering right when compiling corlib */
9828 klass->name = "BuildingObject";
9829 mono_class_setup_parent (klass, mono_defaults.object_class);
9830 klass->name = old_n;
9833 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9834 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9835 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9836 klass->instance_size = sizeof (MonoObject);
9837 klass->size_inited = 1;
9838 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9841 mono_class_setup_mono_type (klass);
9843 mono_class_setup_supertypes (klass);
9846 * FIXME: handle interfaces.
9849 tb->type.type = &klass->byval_arg;
9851 if (tb->nesting_type) {
9852 g_assert (tb->nesting_type->type);
9853 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9856 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9858 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9860 mono_loader_unlock ();
9864 mono_loader_unlock ();
9865 mono_error_raise_exception (&error);
9869 * mono_reflection_setup_generic_class:
9870 * @tb: a TypeBuilder object
9872 * Setup the generic class before adding the first generic parameter.
9875 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9880 * mono_reflection_create_generic_class:
9881 * @tb: a TypeBuilder object
9883 * Creates the generic class after all generic parameters have been added.
9886 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9891 MONO_ARCH_SAVE_REGS;
9893 klass = mono_class_from_mono_type (tb->type.type);
9895 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9897 if (klass->generic_container || (count == 0))
9900 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9902 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9904 klass->generic_container->owner.klass = klass;
9905 klass->generic_container->type_argc = count;
9906 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9908 klass->is_generic = 1;
9910 for (i = 0; i < count; i++) {
9911 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9912 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9913 klass->generic_container->type_params [i] = *param;
9914 /*Make sure we are a diferent type instance */
9915 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9916 klass->generic_container->type_params [i].info.pklass = NULL;
9917 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9919 g_assert (klass->generic_container->type_params [i].param.owner);
9922 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9926 * mono_reflection_create_internal_class:
9927 * @tb: a TypeBuilder object
9929 * Actually create the MonoClass that is associated with the TypeBuilder.
9932 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9936 MONO_ARCH_SAVE_REGS;
9938 klass = mono_class_from_mono_type (tb->type.type);
9940 mono_loader_lock ();
9941 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9942 MonoReflectionFieldBuilder *fb;
9944 MonoType *enum_basetype;
9946 g_assert (tb->fields != NULL);
9947 g_assert (mono_array_length (tb->fields) >= 1);
9949 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9951 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9952 mono_loader_unlock ();
9956 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9957 klass->element_class = mono_class_from_mono_type (enum_basetype);
9958 if (!klass->element_class)
9959 klass->element_class = mono_class_from_mono_type (enum_basetype);
9962 * get the element_class from the current corlib.
9964 ec = default_class_from_mono_type (enum_basetype);
9965 klass->instance_size = ec->instance_size;
9966 klass->size_inited = 1;
9968 * this is almost safe to do with enums and it's needed to be able
9969 * to create objects of the enum type (for use in SetConstant).
9971 /* FIXME: Does this mean enums can't have method overrides ? */
9972 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9974 mono_loader_unlock ();
9977 static MonoMarshalSpec*
9978 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9979 MonoReflectionMarshal *minfo)
9981 MonoMarshalSpec *res;
9983 res = image_g_new0 (image, MonoMarshalSpec, 1);
9984 res->native = minfo->type;
9986 switch (minfo->type) {
9987 case MONO_NATIVE_LPARRAY:
9988 res->data.array_data.elem_type = minfo->eltype;
9989 if (minfo->has_size) {
9990 res->data.array_data.param_num = minfo->param_num;
9991 res->data.array_data.num_elem = minfo->count;
9992 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9995 res->data.array_data.param_num = -1;
9996 res->data.array_data.num_elem = -1;
9997 res->data.array_data.elem_mult = -1;
10001 case MONO_NATIVE_BYVALTSTR:
10002 case MONO_NATIVE_BYVALARRAY:
10003 res->data.array_data.num_elem = minfo->count;
10006 case MONO_NATIVE_CUSTOM:
10007 if (minfo->marshaltyperef)
10008 res->data.custom_data.custom_name =
10009 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10010 if (minfo->mcookie)
10011 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10020 #endif /* !DISABLE_REFLECTION_EMIT */
10022 MonoReflectionMarshal*
10023 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10024 MonoMarshalSpec *spec)
10026 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10027 MonoReflectionMarshal *minfo;
10030 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10031 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10032 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10033 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10036 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10037 minfo->type = spec->native;
10039 switch (minfo->type) {
10040 case MONO_NATIVE_LPARRAY:
10041 minfo->eltype = spec->data.array_data.elem_type;
10042 minfo->count = spec->data.array_data.num_elem;
10043 minfo->param_num = spec->data.array_data.param_num;
10046 case MONO_NATIVE_BYVALTSTR:
10047 case MONO_NATIVE_BYVALARRAY:
10048 minfo->count = spec->data.array_data.num_elem;
10051 case MONO_NATIVE_CUSTOM:
10052 if (spec->data.custom_data.custom_name) {
10053 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10055 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10057 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10059 if (spec->data.custom_data.cookie)
10060 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10070 #ifndef DISABLE_REFLECTION_EMIT
10072 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10073 ReflectionMethodBuilder *rmb,
10074 MonoMethodSignature *sig)
10078 MonoMethodWrapper *wrapperm;
10079 MonoMarshalSpec **specs;
10080 MonoReflectionMethodAux *method_aux;
10085 mono_error_init (&error);
10087 * Methods created using a MethodBuilder should have their memory allocated
10088 * inside the image mempool, while dynamic methods should have their memory
10091 dynamic = rmb->refs != NULL;
10092 image = dynamic ? NULL : klass->image;
10095 g_assert (!klass->generic_class);
10097 mono_loader_lock ();
10099 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10100 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10101 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10103 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10105 wrapperm = (MonoMethodWrapper*)m;
10107 m->dynamic = dynamic;
10109 m->flags = rmb->attrs;
10110 m->iflags = rmb->iattrs;
10111 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10113 m->signature = sig;
10114 m->sre_method = TRUE;
10115 m->skip_visibility = rmb->skip_visibility;
10116 if (rmb->table_idx)
10117 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10119 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10120 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10121 m->string_ctor = 1;
10123 m->signature->pinvoke = 1;
10124 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10125 m->signature->pinvoke = 1;
10127 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10129 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10130 g_assert (mono_error_ok (&error));
10131 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10132 g_assert (mono_error_ok (&error));
10134 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10136 if (klass->image->dynamic)
10137 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10139 mono_loader_unlock ();
10142 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10143 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10144 MonoMethodHeader *header;
10146 gint32 max_stack, i;
10147 gint32 num_locals = 0;
10148 gint32 num_clauses = 0;
10152 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10153 code_size = rmb->ilgen->code_len;
10154 max_stack = rmb->ilgen->max_stack;
10155 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10156 if (rmb->ilgen->ex_handlers)
10157 num_clauses = method_count_clauses (rmb->ilgen);
10160 code = mono_array_addr (rmb->code, guint8, 0);
10161 code_size = mono_array_length (rmb->code);
10162 /* we probably need to run a verifier on the code... */
10172 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10173 header->code_size = code_size;
10174 header->code = image_g_malloc (image, code_size);
10175 memcpy ((char*)header->code, code, code_size);
10176 header->max_stack = max_stack;
10177 header->init_locals = rmb->init_locals;
10178 header->num_locals = num_locals;
10180 for (i = 0; i < num_locals; ++i) {
10181 MonoReflectionLocalBuilder *lb =
10182 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10184 header->locals [i] = image_g_new0 (image, MonoType, 1);
10185 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10188 header->num_clauses = num_clauses;
10190 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10191 rmb->ilgen, num_clauses);
10194 wrapperm->header = header;
10197 if (rmb->generic_params) {
10198 int count = mono_array_length (rmb->generic_params);
10199 MonoGenericContainer *container = rmb->generic_container;
10201 g_assert (container);
10203 container->type_argc = count;
10204 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10205 container->owner.method = m;
10207 m->is_generic = TRUE;
10208 mono_method_set_generic_container (m, container);
10210 for (i = 0; i < count; i++) {
10211 MonoReflectionGenericParam *gp =
10212 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10213 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10214 container->type_params [i] = *param;
10218 * The method signature might have pointers to generic parameters that belong to other methods.
10219 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10220 * generic parameters.
10222 for (i = 0; i < m->signature->param_count; ++i) {
10223 MonoType *t = m->signature->params [i];
10224 if (t->type == MONO_TYPE_MVAR) {
10225 MonoGenericParam *gparam = t->data.generic_param;
10226 if (gparam->num < count) {
10227 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10228 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10234 if (klass->generic_container) {
10235 container->parent = klass->generic_container;
10236 container->context.class_inst = klass->generic_container->context.class_inst;
10238 container->context.method_inst = mono_get_shared_generic_inst (container);
10242 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10246 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10248 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10249 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10250 for (i = 0; i < rmb->nrefs; ++i)
10251 data [i + 1] = rmb->refs [i];
10256 /* Parameter info */
10259 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10260 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10261 for (i = 0; i <= m->signature->param_count; ++i) {
10262 MonoReflectionParamBuilder *pb;
10263 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10264 if ((i > 0) && (pb->attrs)) {
10265 /* Make a copy since it might point to a shared type structure */
10266 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10267 m->signature->params [i - 1]->attrs = pb->attrs;
10270 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10271 MonoDynamicImage *assembly;
10272 guint32 idx, def_type, len;
10276 if (!method_aux->param_defaults) {
10277 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10278 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10280 assembly = (MonoDynamicImage*)klass->image;
10281 idx = encode_constant (assembly, pb->def_value, &def_type);
10282 /* Copy the data from the blob since it might get realloc-ed */
10283 p = assembly->blob.data + idx;
10284 len = mono_metadata_decode_blob_size (p, &p2);
10286 method_aux->param_defaults [i] = image_g_malloc (image, len);
10287 method_aux->param_default_types [i] = def_type;
10288 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10292 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10293 g_assert (mono_error_ok (&error));
10296 if (!method_aux->param_cattr)
10297 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10298 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10304 /* Parameter marshalling */
10307 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10308 MonoReflectionParamBuilder *pb;
10309 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10310 if (pb->marshal_info) {
10312 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10313 specs [pb->position] =
10314 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10318 if (specs != NULL) {
10320 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10321 method_aux->param_marshall = specs;
10324 if (klass->image->dynamic && method_aux)
10325 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10327 mono_loader_unlock ();
10333 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10335 ReflectionMethodBuilder rmb;
10336 MonoMethodSignature *sig;
10338 mono_loader_lock ();
10339 sig = ctor_builder_to_signature (klass->image, mb);
10340 mono_loader_unlock ();
10342 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10344 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10345 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10347 /* If we are in a generic class, we might be called multiple times from inflate_method */
10348 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10349 /* ilgen is no longer needed */
10353 return mb->mhandle;
10357 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10359 ReflectionMethodBuilder rmb;
10360 MonoMethodSignature *sig;
10362 mono_loader_lock ();
10363 sig = method_builder_to_signature (klass->image, mb);
10364 mono_loader_unlock ();
10366 reflection_methodbuilder_from_method_builder (&rmb, mb);
10368 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10369 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10371 /* If we are in a generic class, we might be called multiple times from inflate_method */
10372 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10373 /* ilgen is no longer needed */
10376 return mb->mhandle;
10379 static MonoClassField*
10380 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10382 MonoClassField *field;
10386 field = g_new0 (MonoClassField, 1);
10388 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10389 g_assert (mono_error_ok (&error));
10390 if (fb->attrs || fb->modreq || fb->modopt) {
10391 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10392 field->type->attrs = fb->attrs;
10394 g_assert (klass->image->dynamic);
10395 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10396 g_free (field->type);
10397 field->type = mono_metadata_type_dup (klass->image, custom);
10400 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10402 if (fb->offset != -1)
10403 field->offset = fb->offset;
10404 field->parent = klass;
10405 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10407 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10414 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10417 MonoReflectionTypeBuilder *tb = NULL;
10418 gboolean is_dynamic = FALSE;
10419 MonoDomain *domain;
10420 MonoClass *geninst;
10422 mono_loader_lock ();
10424 domain = mono_object_domain (type);
10426 if (is_sre_type_builder (mono_object_class (type))) {
10427 tb = (MonoReflectionTypeBuilder *) type;
10430 } else if (is_sre_generic_instance (mono_object_class (type))) {
10431 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10432 MonoReflectionType *gtd = rgi->generic_type;
10434 if (is_sre_type_builder (mono_object_class (gtd))) {
10435 tb = (MonoReflectionTypeBuilder *)gtd;
10440 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10441 if (tb && tb->generic_container)
10442 mono_reflection_create_generic_class (tb);
10444 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10445 if (!klass->generic_container) {
10446 mono_loader_unlock ();
10450 if (klass->wastypebuilder) {
10451 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10456 mono_loader_unlock ();
10458 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10460 return &geninst->byval_arg;
10464 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10466 MonoGenericClass *gclass;
10467 MonoGenericInst *inst;
10469 g_assert (klass->generic_container);
10471 inst = mono_metadata_get_generic_inst (type_argc, types);
10472 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10474 return mono_generic_class_get_class (gclass);
10477 MonoReflectionMethod*
10478 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10481 MonoMethod *method, *inflated;
10482 MonoMethodInflated *imethod;
10483 MonoGenericContext tmp_context;
10484 MonoGenericInst *ginst;
10485 MonoType **type_argv;
10488 MONO_ARCH_SAVE_REGS;
10490 /*FIXME but this no longer should happen*/
10491 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10492 #ifndef DISABLE_REFLECTION_EMIT
10493 MonoReflectionMethodBuilder *mb = NULL;
10494 MonoReflectionTypeBuilder *tb;
10497 mb = (MonoReflectionMethodBuilder *) rmethod;
10498 tb = (MonoReflectionTypeBuilder *) mb->type;
10499 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10501 method = methodbuilder_to_mono_method (klass, mb);
10503 g_assert_not_reached ();
10507 method = rmethod->method;
10510 klass = method->klass;
10512 if (method->is_inflated)
10513 method = ((MonoMethodInflated *) method)->declaring;
10515 count = mono_method_signature (method)->generic_param_count;
10516 if (count != mono_array_length (types))
10519 type_argv = g_new0 (MonoType *, count);
10520 for (i = 0; i < count; i++) {
10521 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10522 type_argv [i] = mono_reflection_type_get_handle (garg);
10524 ginst = mono_metadata_get_generic_inst (count, type_argv);
10525 g_free (type_argv);
10527 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10528 tmp_context.method_inst = ginst;
10530 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10531 imethod = (MonoMethodInflated *) inflated;
10533 /*FIXME but I think this is no longer necessary*/
10534 if (method->klass->image->dynamic) {
10535 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10537 * This table maps metadata structures representing inflated methods/fields
10538 * to the reflection objects representing their generic definitions.
10540 mono_loader_lock ();
10541 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10542 mono_loader_unlock ();
10545 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10546 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10548 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10551 #ifndef DISABLE_REFLECTION_EMIT
10553 static MonoMethod *
10554 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10556 MonoMethodInflated *imethod;
10557 MonoGenericContext *context;
10561 * With generic code sharing the klass might not be inflated.
10562 * This can happen because classes inflated with their own
10563 * type arguments are "normalized" to the uninflated class.
10565 if (!klass->generic_class)
10568 context = mono_class_get_context (klass);
10570 if (klass->method.count && klass->methods) {
10571 /* Find the already created inflated method */
10572 for (i = 0; i < klass->method.count; ++i) {
10573 g_assert (klass->methods [i]->is_inflated);
10574 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10577 g_assert (i < klass->method.count);
10578 imethod = (MonoMethodInflated*)klass->methods [i];
10580 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10583 if (method->is_generic && method->klass->image->dynamic) {
10584 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10586 mono_loader_lock ();
10587 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10588 mono_loader_unlock ();
10590 return (MonoMethod *) imethod;
10593 static MonoMethod *
10594 inflate_method (MonoReflectionType *type, MonoObject *obj)
10596 MonoMethod *method;
10599 MonoClass *type_class = mono_object_class (type);
10601 if (is_sre_generic_instance (type_class)) {
10602 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10603 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10604 } else if (is_sre_type_builder (type_class)) {
10605 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10606 } else if (type->type) {
10607 gklass = mono_class_from_mono_type (type->type);
10608 gklass = mono_class_get_generic_type_definition (gklass);
10610 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10613 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10614 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10615 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10617 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10618 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10619 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10620 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10621 method = ((MonoReflectionMethod *) obj)->method;
10623 method = NULL; /* prevent compiler warning */
10624 g_error ("can't handle type %s", obj->vtable->klass->name);
10627 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10630 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10632 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10634 MonoGenericClass *gclass;
10635 MonoDynamicGenericClass *dgclass;
10636 MonoClass *klass, *gklass;
10640 MONO_ARCH_SAVE_REGS;
10642 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10643 klass = mono_class_from_mono_type (gtype);
10644 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10645 gclass = gtype->data.generic_class;
10647 if (!gclass->is_dynamic)
10650 dgclass = (MonoDynamicGenericClass *) gclass;
10652 if (dgclass->initialized)
10655 gklass = gclass->container_class;
10656 mono_class_init (gklass);
10658 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10660 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10661 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10662 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10664 for (i = 0; i < dgclass->count_fields; i++) {
10665 MonoObject *obj = mono_array_get (fields, gpointer, i);
10666 MonoClassField *field, *inflated_field = NULL;
10668 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10669 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10670 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10671 field = ((MonoReflectionField *) obj)->field;
10673 field = NULL; /* prevent compiler warning */
10674 g_assert_not_reached ();
10677 dgclass->fields [i] = *field;
10678 dgclass->fields [i].parent = klass;
10679 dgclass->fields [i].type = mono_class_inflate_generic_type (
10680 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10681 dgclass->field_generic_types [i] = field->type;
10682 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10683 dgclass->field_objects [i] = obj;
10685 if (inflated_field) {
10686 g_free (inflated_field);
10688 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10692 dgclass->initialized = TRUE;
10696 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10698 MonoDynamicGenericClass *dgclass;
10701 g_assert (gclass->is_dynamic);
10703 dgclass = (MonoDynamicGenericClass *)gclass;
10705 for (i = 0; i < dgclass->count_fields; ++i) {
10706 MonoClassField *field = dgclass->fields + i;
10707 mono_metadata_free_type (field->type);
10708 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10713 fix_partial_generic_class (MonoClass *klass)
10715 MonoClass *gklass = klass->generic_class->container_class;
10716 MonoDynamicGenericClass *dgclass;
10719 if (klass->wastypebuilder)
10722 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10723 if (klass->parent != gklass->parent) {
10725 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10726 if (mono_error_ok (&error)) {
10727 MonoClass *parent = mono_class_from_mono_type (parent_type);
10728 mono_metadata_free_type (parent_type);
10729 if (parent != klass->parent) {
10730 /*fool mono_class_setup_parent*/
10731 klass->supertypes = NULL;
10732 mono_class_setup_parent (klass, parent);
10735 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10736 mono_error_cleanup (&error);
10737 if (gklass->wastypebuilder)
10738 klass->wastypebuilder = TRUE;
10743 if (!dgclass->initialized)
10746 if (klass->method.count != gklass->method.count) {
10747 klass->method.count = gklass->method.count;
10748 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10750 for (i = 0; i < klass->method.count; i++) {
10751 klass->methods [i] = mono_class_inflate_generic_method_full (
10752 gklass->methods [i], klass, mono_class_get_context (klass));
10756 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10757 klass->interface_count = gklass->interface_count;
10758 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10759 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10761 for (i = 0; i < gklass->interface_count; ++i) {
10762 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10763 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10764 mono_metadata_free_type (iface_type);
10766 ensure_runtime_vtable (klass->interfaces [i]);
10768 klass->interfaces_inited = 1;
10771 if (klass->field.count != gklass->field.count) {
10772 klass->field.count = gklass->field.count;
10773 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10775 for (i = 0; i < klass->field.count; i++) {
10776 klass->fields [i] = gklass->fields [i];
10777 klass->fields [i].parent = klass;
10778 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10782 /*We can only finish with this klass once it's parent has as well*/
10783 if (gklass->wastypebuilder)
10784 klass->wastypebuilder = TRUE;
10789 ensure_generic_class_runtime_vtable (MonoClass *klass)
10791 MonoClass *gklass = klass->generic_class->container_class;
10793 ensure_runtime_vtable (gklass);
10795 fix_partial_generic_class (klass);
10799 ensure_runtime_vtable (MonoClass *klass)
10801 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10804 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10807 ensure_runtime_vtable (klass->parent);
10810 num = tb->ctors? mono_array_length (tb->ctors): 0;
10811 num += tb->num_methods;
10812 klass->method.count = num;
10813 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10814 num = tb->ctors? mono_array_length (tb->ctors): 0;
10815 for (i = 0; i < num; ++i)
10816 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10817 num = tb->num_methods;
10819 for (i = 0; i < num; ++i)
10820 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10822 if (tb->interfaces) {
10823 klass->interface_count = mono_array_length (tb->interfaces);
10824 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10825 for (i = 0; i < klass->interface_count; ++i) {
10826 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10827 klass->interfaces [i] = mono_class_from_mono_type (iface);
10828 ensure_runtime_vtable (klass->interfaces [i]);
10830 klass->interfaces_inited = 1;
10832 } else if (klass->generic_class){
10833 ensure_generic_class_runtime_vtable (klass);
10836 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10838 for (i = 0; i < klass->method.count; ++i) {
10839 MonoMethod *im = klass->methods [i];
10840 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10841 im->slot = slot_num++;
10844 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10845 mono_class_setup_interface_offsets (klass);
10846 mono_class_setup_interface_id (klass);
10850 * The generic vtable is needed even if image->run is not set since some
10851 * runtime code like ves_icall_Type_GetMethodsByName depends on
10852 * method->slot being defined.
10856 * tb->methods could not be freed since it is used for determining
10857 * overrides during dynamic vtable construction.
10862 mono_reflection_method_get_handle (MonoObject *method)
10864 MonoClass *class = mono_object_class (method);
10865 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10866 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10867 return sr_method->method;
10869 if (is_sre_method_builder (class)) {
10870 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10871 return mb->mhandle;
10873 if (is_sre_method_on_tb_inst (class)) {
10874 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10875 MonoMethod *result;
10876 /*FIXME move this to a proper method and unify with resolve_object*/
10877 if (m->method_args) {
10878 result = mono_reflection_method_on_tb_inst_get_handle (m);
10880 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10881 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10882 MonoMethod *mono_method;
10884 if (is_sre_method_builder (mono_object_class (m->mb)))
10885 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10886 else if (is_sr_mono_method (mono_object_class (m->mb)))
10887 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10889 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)));
10891 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10896 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10901 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10903 MonoReflectionTypeBuilder *tb;
10905 MonoReflectionMethod *m;
10908 *num_overrides = 0;
10910 g_assert (klass->image->dynamic);
10912 if (!mono_class_get_ref_info (klass))
10915 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10917 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10921 for (i = 0; i < tb->num_methods; ++i) {
10922 MonoReflectionMethodBuilder *mb =
10923 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10924 if (mb->override_methods)
10925 onum += mono_array_length (mb->override_methods);
10930 *overrides = g_new0 (MonoMethod*, onum * 2);
10933 for (i = 0; i < tb->num_methods; ++i) {
10934 MonoReflectionMethodBuilder *mb =
10935 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10936 if (mb->override_methods) {
10937 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10938 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10940 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10941 (*overrides) [onum * 2 + 1] = mb->mhandle;
10943 g_assert (mb->mhandle);
10951 *num_overrides = onum;
10955 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10957 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10958 MonoReflectionFieldBuilder *fb;
10959 MonoClassField *field;
10960 MonoImage *image = klass->image;
10961 const char *p, *p2;
10963 guint32 len, idx, real_size = 0;
10965 klass->field.count = tb->num_fields;
10966 klass->field.first = 0;
10968 mono_error_init (error);
10970 if (tb->class_size) {
10971 if ((tb->packing_size & 0xfffffff0) != 0) {
10972 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10973 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10976 klass->packing_size = tb->packing_size;
10977 real_size = klass->instance_size + tb->class_size;
10980 if (!klass->field.count) {
10981 klass->instance_size = MAX (klass->instance_size, real_size);
10985 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10986 mono_class_alloc_ext (klass);
10987 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10989 This is, guess what, a hack.
10990 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10991 On the static path no field class is resolved, only types are built. This is the right thing to do
10993 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10995 klass->size_inited = 1;
10997 for (i = 0; i < klass->field.count; ++i) {
10998 MonoArray *rva_data;
10999 fb = mono_array_get (tb->fields, gpointer, i);
11000 field = &klass->fields [i];
11001 field->name = mono_string_to_utf8_image (image, fb->name, error);
11002 if (!mono_error_ok (error))
11005 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11006 field->type->attrs = fb->attrs;
11008 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11011 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11012 char *base = mono_array_addr (rva_data, char, 0);
11013 size_t size = mono_array_length (rva_data);
11014 char *data = mono_image_alloc (klass->image, size);
11015 memcpy (data, base, size);
11016 klass->ext->field_def_values [i].data = data;
11018 if (fb->offset != -1)
11019 field->offset = fb->offset;
11020 field->parent = klass;
11021 fb->handle = field;
11022 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11024 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11025 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11027 if (fb->def_value) {
11028 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11029 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11030 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11031 /* Copy the data from the blob since it might get realloc-ed */
11032 p = assembly->blob.data + idx;
11033 len = mono_metadata_decode_blob_size (p, &p2);
11035 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11036 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11040 klass->instance_size = MAX (klass->instance_size, real_size);
11041 mono_class_layout_fields (klass);
11045 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11047 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11048 MonoReflectionPropertyBuilder *pb;
11049 MonoImage *image = klass->image;
11050 MonoProperty *properties;
11053 mono_error_init (error);
11056 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11058 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11059 klass->ext->property.first = 0;
11061 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11062 klass->ext->properties = properties;
11063 for (i = 0; i < klass->ext->property.count; ++i) {
11064 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11065 properties [i].parent = klass;
11066 properties [i].attrs = pb->attrs;
11067 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11068 if (!mono_error_ok (error))
11070 if (pb->get_method)
11071 properties [i].get = pb->get_method->mhandle;
11072 if (pb->set_method)
11073 properties [i].set = pb->set_method->mhandle;
11075 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11076 if (pb->def_value) {
11078 const char *p, *p2;
11079 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11080 if (!klass->ext->prop_def_values)
11081 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11082 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11083 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11084 /* Copy the data from the blob since it might get realloc-ed */
11085 p = assembly->blob.data + idx;
11086 len = mono_metadata_decode_blob_size (p, &p2);
11088 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11089 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11094 MonoReflectionEvent *
11095 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11097 MonoEvent *event = g_new0 (MonoEvent, 1);
11100 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11102 event->parent = klass;
11103 event->attrs = eb->attrs;
11104 event->name = mono_string_to_utf8 (eb->name);
11105 if (eb->add_method)
11106 event->add = eb->add_method->mhandle;
11107 if (eb->remove_method)
11108 event->remove = eb->remove_method->mhandle;
11109 if (eb->raise_method)
11110 event->raise = eb->raise_method->mhandle;
11112 #ifndef MONO_SMALL_CONFIG
11113 if (eb->other_methods) {
11115 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11116 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11117 MonoReflectionMethodBuilder *mb =
11118 mono_array_get (eb->other_methods,
11119 MonoReflectionMethodBuilder*, j);
11120 event->other [j] = mb->mhandle;
11125 return mono_event_get_object (mono_object_domain (tb), klass, event);
11129 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11131 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11132 MonoReflectionEventBuilder *eb;
11133 MonoImage *image = klass->image;
11137 mono_error_init (error);
11140 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11142 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11143 klass->ext->event.first = 0;
11145 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11146 klass->ext->events = events;
11147 for (i = 0; i < klass->ext->event.count; ++i) {
11148 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11149 events [i].parent = klass;
11150 events [i].attrs = eb->attrs;
11151 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11152 if (!mono_error_ok (error))
11154 if (eb->add_method)
11155 events [i].add = eb->add_method->mhandle;
11156 if (eb->remove_method)
11157 events [i].remove = eb->remove_method->mhandle;
11158 if (eb->raise_method)
11159 events [i].raise = eb->raise_method->mhandle;
11161 #ifndef MONO_SMALL_CONFIG
11162 if (eb->other_methods) {
11164 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11165 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11166 MonoReflectionMethodBuilder *mb =
11167 mono_array_get (eb->other_methods,
11168 MonoReflectionMethodBuilder*, j);
11169 events [i].other [j] = mb->mhandle;
11173 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11178 remove_instantiations_of_and_ensure_contents (gpointer key,
11180 gpointer user_data)
11182 MonoType *type = (MonoType*)key;
11183 MonoClass *klass = (MonoClass*)user_data;
11185 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11186 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11193 check_array_for_usertypes (MonoArray *arr)
11200 for (i = 0; i < mono_array_length (arr); ++i)
11201 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11204 MonoReflectionType*
11205 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11209 MonoDomain* domain;
11210 MonoReflectionType* res;
11213 MONO_ARCH_SAVE_REGS;
11215 domain = mono_object_domain (tb);
11216 klass = mono_class_from_mono_type (tb->type.type);
11219 * Check for user defined Type subclasses.
11221 RESOLVE_TYPE (tb->parent);
11222 check_array_for_usertypes (tb->interfaces);
11224 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11225 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11227 RESOLVE_TYPE (fb->type);
11228 check_array_for_usertypes (fb->modreq);
11229 check_array_for_usertypes (fb->modopt);
11230 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11231 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11236 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11237 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11239 RESOLVE_TYPE (mb->rtype);
11240 check_array_for_usertypes (mb->return_modreq);
11241 check_array_for_usertypes (mb->return_modopt);
11242 check_array_for_usertypes (mb->parameters);
11243 if (mb->param_modreq)
11244 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11245 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11246 if (mb->param_modopt)
11247 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11248 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11253 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11254 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11256 check_array_for_usertypes (mb->parameters);
11257 if (mb->param_modreq)
11258 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11259 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11260 if (mb->param_modopt)
11261 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11262 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11267 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11270 * we need to lock the domain because the lock will be taken inside
11271 * So, we need to keep the locking order correct.
11273 mono_loader_lock ();
11274 mono_domain_lock (domain);
11275 if (klass->wastypebuilder) {
11276 mono_domain_unlock (domain);
11277 mono_loader_unlock ();
11278 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11281 * Fields to set in klass:
11282 * the various flags: delegate/unicode/contextbound etc.
11284 klass->flags = tb->attrs;
11285 klass->has_cctor = 1;
11286 klass->has_finalize = 1;
11287 klass->has_finalize_inited = 1;
11289 /* fool mono_class_setup_parent */
11290 klass->supertypes = NULL;
11291 mono_class_setup_parent (klass, klass->parent);
11292 mono_class_setup_mono_type (klass);
11295 if (!((MonoDynamicImage*)klass->image)->run) {
11296 if (klass->generic_container) {
11297 /* FIXME: The code below can't handle generic classes */
11298 klass->wastypebuilder = TRUE;
11299 mono_loader_unlock ();
11300 mono_domain_unlock (domain);
11301 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11306 /* enums are done right away */
11307 if (!klass->enumtype)
11308 ensure_runtime_vtable (klass);
11310 if (tb->subtypes) {
11311 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11312 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11313 mono_class_alloc_ext (klass);
11314 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)));
11318 klass->nested_classes_inited = TRUE;
11320 /* fields and object layout */
11321 if (klass->parent) {
11322 if (!klass->parent->size_inited)
11323 mono_class_init (klass->parent);
11324 klass->instance_size = klass->parent->instance_size;
11325 klass->sizes.class_size = 0;
11326 klass->min_align = klass->parent->min_align;
11327 /* if the type has no fields we won't call the field_setup
11328 * routine which sets up klass->has_references.
11330 klass->has_references |= klass->parent->has_references;
11332 klass->instance_size = sizeof (MonoObject);
11333 klass->min_align = 1;
11336 /* FIXME: handle packing_size and instance_size */
11337 typebuilder_setup_fields (klass, &error);
11338 if (!mono_error_ok (&error))
11340 typebuilder_setup_properties (klass, &error);
11341 if (!mono_error_ok (&error))
11344 typebuilder_setup_events (klass, &error);
11345 if (!mono_error_ok (&error))
11348 klass->wastypebuilder = TRUE;
11351 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11352 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11353 * we want to return normal System.MonoType objects, so clear these out from the cache.
11355 * Together with this we must ensure the contents of all instances to match the created type.
11357 if (domain->type_hash && klass->generic_container)
11358 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11360 mono_domain_unlock (domain);
11361 mono_loader_unlock ();
11363 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11364 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11365 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11368 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11369 g_assert (res != (MonoReflectionType*)tb);
11374 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11375 klass->wastypebuilder = TRUE;
11376 mono_domain_unlock (domain);
11377 mono_loader_unlock ();
11378 mono_error_raise_exception (&error);
11383 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11385 MonoGenericParamFull *param;
11390 MONO_ARCH_SAVE_REGS;
11392 image = &gparam->tbuilder->module->dynamic_image->image;
11394 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11396 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11397 g_assert (mono_error_ok (&error));
11398 param->param.num = gparam->index;
11400 if (gparam->mbuilder) {
11401 if (!gparam->mbuilder->generic_container) {
11402 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11403 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11404 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11405 gparam->mbuilder->generic_container->is_method = TRUE;
11407 * Cannot set owner.method, since the MonoMethod is not created yet.
11408 * Set the image field instead, so type_in_image () works.
11410 gparam->mbuilder->generic_container->image = klass->image;
11412 param->param.owner = gparam->mbuilder->generic_container;
11413 } else if (gparam->tbuilder) {
11414 if (!gparam->tbuilder->generic_container) {
11415 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11416 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11417 gparam->tbuilder->generic_container->owner.klass = klass;
11419 param->param.owner = gparam->tbuilder->generic_container;
11422 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11424 gparam->type.type = &pklass->byval_arg;
11426 mono_class_set_ref_info (pklass, gparam);
11427 mono_image_lock (image);
11428 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11429 mono_image_unlock (image);
11433 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11435 MonoReflectionModuleBuilder *module = sig->module;
11436 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11437 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11442 check_array_for_usertypes (sig->arguments);
11444 sigbuffer_init (&buf, 32);
11446 sigbuffer_add_value (&buf, 0x07);
11447 sigbuffer_add_value (&buf, na);
11448 if (assembly != NULL){
11449 for (i = 0; i < na; ++i) {
11450 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11451 encode_reflection_type (assembly, type, &buf);
11455 buflen = buf.p - buf.buf;
11456 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11457 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11458 sigbuffer_free (&buf);
11464 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11466 MonoDynamicImage *assembly = sig->module->dynamic_image;
11467 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11472 check_array_for_usertypes (sig->arguments);
11474 sigbuffer_init (&buf, 32);
11476 sigbuffer_add_value (&buf, 0x06);
11477 for (i = 0; i < na; ++i) {
11478 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11479 encode_reflection_type (assembly, type, &buf);
11482 buflen = buf.p - buf.buf;
11483 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11484 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11485 sigbuffer_free (&buf);
11491 MonoMethod *handle;
11492 MonoDomain *domain;
11493 } DynamicMethodReleaseData;
11496 * The runtime automatically clean up those after finalization.
11498 static MonoReferenceQueue *dynamic_method_queue;
11501 free_dynamic_method (void *dynamic_method)
11503 DynamicMethodReleaseData *data = dynamic_method;
11505 mono_runtime_free_method (data->domain, data->handle);
11510 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11512 MonoReferenceQueue *queue;
11513 MonoMethod *handle;
11514 DynamicMethodReleaseData *release_data;
11515 ReflectionMethodBuilder rmb;
11516 MonoMethodSignature *sig;
11521 if (mono_runtime_is_shutting_down ())
11522 mono_raise_exception (mono_get_exception_invalid_operation (""));
11524 if (!(queue = dynamic_method_queue)) {
11525 mono_loader_lock ();
11526 if (!(queue = dynamic_method_queue))
11527 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11528 mono_loader_unlock ();
11531 sig = dynamic_method_to_signature (mb);
11533 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11536 * Resolve references.
11539 * Every second entry in the refs array is reserved for storing handle_class,
11540 * which is needed by the ldtoken implementation in the JIT.
11542 rmb.nrefs = mb->nrefs;
11543 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11544 for (i = 0; i < mb->nrefs; i += 2) {
11545 MonoClass *handle_class;
11547 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11549 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11550 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11552 * The referenced DynamicMethod should already be created by the managed
11553 * code, except in the case of circular references. In that case, we store
11554 * method in the refs array, and fix it up later when the referenced
11555 * DynamicMethod is created.
11557 if (method->mhandle) {
11558 ref = method->mhandle;
11560 /* FIXME: GC object stored in unmanaged memory */
11563 /* FIXME: GC object stored in unmanaged memory */
11564 method->referenced_by = g_slist_append (method->referenced_by, mb);
11566 handle_class = mono_defaults.methodhandle_class;
11568 MonoException *ex = NULL;
11569 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11571 ex = mono_get_exception_type_load (NULL, NULL);
11572 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11573 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11577 mono_raise_exception (ex);
11582 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11583 rmb.refs [i + 1] = handle_class;
11586 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11588 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11589 release_data = g_new (DynamicMethodReleaseData, 1);
11590 release_data->handle = handle;
11591 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11592 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11593 g_free (release_data);
11595 /* Fix up refs entries pointing at us */
11596 for (l = mb->referenced_by; l; l = l->next) {
11597 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11598 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11601 g_assert (method->mhandle);
11603 data = (gpointer*)wrapper->method_data;
11604 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11605 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11606 data [i + 1] = mb->mhandle;
11609 g_slist_free (mb->referenced_by);
11613 /* ilgen is no longer needed */
11617 #endif /* DISABLE_REFLECTION_EMIT */
11621 * mono_reflection_is_valid_dynamic_token:
11623 * Returns TRUE if token is valid.
11627 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11629 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11632 MonoMethodSignature *
11633 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11635 MonoMethodSignature *sig;
11636 g_assert (image->dynamic);
11638 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11642 return mono_method_signature (method);
11645 #ifndef DISABLE_REFLECTION_EMIT
11648 * mono_reflection_lookup_dynamic_token:
11650 * Finish the Builder object pointed to by TOKEN and return the corresponding
11651 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11652 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11655 * LOCKING: Take the loader lock
11658 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11660 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11664 mono_loader_lock ();
11665 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11666 mono_loader_unlock ();
11669 g_error ("Could not find required dynamic token 0x%08x", token);
11675 handle_class = &klass;
11676 return resolve_object (image, obj, handle_class, context);
11680 * ensure_complete_type:
11682 * Ensure that KLASS is completed if it is a dynamic type, or references
11686 ensure_complete_type (MonoClass *klass)
11688 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11689 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11691 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11693 // Asserting here could break a lot of code
11694 //g_assert (klass->wastypebuilder);
11697 if (klass->generic_class) {
11698 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11701 for (i = 0; i < inst->type_argc; ++i) {
11702 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11708 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11710 gpointer result = NULL;
11712 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11713 result = mono_string_intern ((MonoString*)obj);
11714 *handle_class = mono_defaults.string_class;
11716 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11717 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11718 MonoClass *mc = mono_class_from_mono_type (type);
11719 if (!mono_class_init (mc))
11720 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11723 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11724 result = mono_class_from_mono_type (inflated);
11725 mono_metadata_free_type (inflated);
11727 result = mono_class_from_mono_type (type);
11729 *handle_class = mono_defaults.typehandle_class;
11731 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11732 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11733 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11734 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11735 result = ((MonoReflectionMethod*)obj)->method;
11737 result = mono_class_inflate_generic_method (result, context);
11738 *handle_class = mono_defaults.methodhandle_class;
11740 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11741 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11742 result = mb->mhandle;
11744 /* Type is not yet created */
11745 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11747 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11750 * Hopefully this has been filled in by calling CreateType() on the
11754 * TODO: This won't work if the application finishes another
11755 * TypeBuilder instance instead of this one.
11757 result = mb->mhandle;
11760 result = mono_class_inflate_generic_method (result, context);
11761 *handle_class = mono_defaults.methodhandle_class;
11762 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11763 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11765 result = cb->mhandle;
11767 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11769 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11770 result = cb->mhandle;
11773 result = mono_class_inflate_generic_method (result, context);
11774 *handle_class = mono_defaults.methodhandle_class;
11775 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11776 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11778 ensure_complete_type (field->parent);
11780 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11781 MonoClass *class = mono_class_from_mono_type (inflated);
11782 MonoClassField *inflated_field;
11783 gpointer iter = NULL;
11784 mono_metadata_free_type (inflated);
11785 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11786 if (!strcmp (field->name, inflated_field->name))
11789 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11790 result = inflated_field;
11794 *handle_class = mono_defaults.fieldhandle_class;
11796 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11797 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11798 result = fb->handle;
11801 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11803 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11804 result = fb->handle;
11807 if (fb->handle && fb->handle->parent->generic_container) {
11808 MonoClass *klass = fb->handle->parent;
11809 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11810 MonoClass *inflated = mono_class_from_mono_type (type);
11812 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11814 mono_metadata_free_type (type);
11816 *handle_class = mono_defaults.fieldhandle_class;
11817 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11818 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11819 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11822 klass = type->data.klass;
11823 if (klass->wastypebuilder) {
11824 /* Already created */
11828 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11829 result = type->data.klass;
11832 *handle_class = mono_defaults.typehandle_class;
11833 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11834 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11835 MonoMethodSignature *sig;
11838 if (helper->arguments)
11839 nargs = mono_array_length (helper->arguments);
11843 sig = mono_metadata_signature_alloc (image, nargs);
11844 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11845 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11847 if (helper->unmanaged_call_conv) { /* unmanaged */
11848 sig->call_convention = helper->unmanaged_call_conv - 1;
11849 sig->pinvoke = TRUE;
11850 } else if (helper->call_conv & 0x02) {
11851 sig->call_convention = MONO_CALL_VARARG;
11853 sig->call_convention = MONO_CALL_DEFAULT;
11856 sig->param_count = nargs;
11857 /* TODO: Copy type ? */
11858 sig->ret = helper->return_type->type;
11859 for (i = 0; i < nargs; ++i)
11860 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11863 *handle_class = NULL;
11864 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11865 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11866 /* Already created by the managed code */
11867 g_assert (method->mhandle);
11868 result = method->mhandle;
11869 *handle_class = mono_defaults.methodhandle_class;
11870 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11871 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11872 type = mono_class_inflate_generic_type (type, context);
11873 result = mono_class_from_mono_type (type);
11874 *handle_class = mono_defaults.typehandle_class;
11876 mono_metadata_free_type (type);
11877 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11878 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11879 type = mono_class_inflate_generic_type (type, context);
11880 result = mono_class_from_mono_type (type);
11881 *handle_class = mono_defaults.typehandle_class;
11883 mono_metadata_free_type (type);
11884 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11885 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11886 MonoClass *inflated;
11888 MonoClassField *field;
11890 if (is_sre_field_builder (mono_object_class (f->fb)))
11891 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11892 else if (is_sr_mono_field (mono_object_class (f->fb)))
11893 field = ((MonoReflectionField*)f->fb)->field;
11895 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)));
11897 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11898 inflated = mono_class_from_mono_type (type);
11900 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11901 ensure_complete_type (field->parent);
11903 mono_metadata_free_type (type);
11904 *handle_class = mono_defaults.fieldhandle_class;
11905 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11906 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11907 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11908 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11909 MonoMethod *method;
11911 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11912 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11913 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11914 method = ((MonoReflectionMethod *)c->cb)->method;
11916 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)));
11918 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11919 *handle_class = mono_defaults.methodhandle_class;
11920 mono_metadata_free_type (type);
11921 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11922 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11923 if (m->method_args) {
11924 result = mono_reflection_method_on_tb_inst_get_handle (m);
11926 result = mono_class_inflate_generic_method (result, context);
11928 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11929 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11930 MonoMethod *method;
11932 if (is_sre_method_builder (mono_object_class (m->mb)))
11933 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11934 else if (is_sr_mono_method (mono_object_class (m->mb)))
11935 method = ((MonoReflectionMethod *)m->mb)->method;
11937 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)));
11939 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11940 mono_metadata_free_type (type);
11942 *handle_class = mono_defaults.methodhandle_class;
11943 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11944 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11947 MonoMethod *method;
11951 mtype = mono_reflection_type_get_handle (m->parent);
11952 klass = mono_class_from_mono_type (mtype);
11954 /* Find the method */
11956 name = mono_string_to_utf8 (m->name);
11958 while ((method = mono_class_get_methods (klass, &iter))) {
11959 if (!strcmp (method->name, name))
11966 // FIXME: Check parameters/return value etc. match
11969 *handle_class = mono_defaults.methodhandle_class;
11970 } else if (is_sre_array (mono_object_get_class(obj)) ||
11971 is_sre_byref (mono_object_get_class(obj)) ||
11972 is_sre_pointer (mono_object_get_class(obj))) {
11973 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11974 MonoType *type = mono_reflection_type_get_handle (ref_type);
11977 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11978 result = mono_class_from_mono_type (inflated);
11979 mono_metadata_free_type (inflated);
11981 result = mono_class_from_mono_type (type);
11983 *handle_class = mono_defaults.typehandle_class;
11985 g_print ("%s\n", obj->vtable->klass->name);
11986 g_assert_not_reached ();
11991 #else /* DISABLE_REFLECTION_EMIT */
11994 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11996 g_assert_not_reached ();
12001 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12003 g_assert_not_reached ();
12007 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12009 g_assert_not_reached ();
12013 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12015 g_assert_not_reached ();
12019 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12021 g_assert_not_reached ();
12025 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12027 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12031 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12033 g_assert_not_reached ();
12037 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12039 g_assert_not_reached ();
12042 MonoReflectionModule *
12043 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12045 g_assert_not_reached ();
12050 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12052 g_assert_not_reached ();
12057 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12059 g_assert_not_reached ();
12064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12065 gboolean create_open_instance, gboolean register_token)
12067 g_assert_not_reached ();
12072 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12077 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12079 g_assert_not_reached ();
12083 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12086 *num_overrides = 0;
12089 MonoReflectionEvent *
12090 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12092 g_assert_not_reached ();
12096 MonoReflectionType*
12097 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12099 g_assert_not_reached ();
12104 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12106 g_assert_not_reached ();
12110 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12112 g_assert_not_reached ();
12117 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12119 g_assert_not_reached ();
12124 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12129 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12135 mono_reflection_type_get_handle (MonoReflectionType* ref)
12143 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12145 g_assert_not_reached ();
12148 #endif /* DISABLE_REFLECTION_EMIT */
12150 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12151 const static guint32 declsec_flags_map[] = {
12152 0x00000000, /* empty */
12153 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12154 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12155 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12156 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12157 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12158 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12159 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12160 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12161 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12162 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12163 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12164 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12165 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12166 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12167 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12168 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12169 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12170 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12174 * Returns flags that includes all available security action associated to the handle.
12175 * @token: metadata token (either for a class or a method)
12176 * @image: image where resides the metadata.
12179 mono_declsec_get_flags (MonoImage *image, guint32 token)
12181 int index = mono_metadata_declsec_from_index (image, token);
12182 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12183 guint32 result = 0;
12187 /* HasSecurity can be present for other, not specially encoded, attributes,
12188 e.g. SuppressUnmanagedCodeSecurityAttribute */
12192 for (i = index; i < t->rows; i++) {
12193 guint32 cols [MONO_DECL_SECURITY_SIZE];
12195 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12196 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12199 action = cols [MONO_DECL_SECURITY_ACTION];
12200 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12201 result |= declsec_flags_map [action];
12203 g_assert_not_reached ();
12210 * Get the security actions (in the form of flags) associated with the specified method.
12212 * @method: The method for which we want the declarative security flags.
12213 * Return the declarative security flags for the method (only).
12215 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12216 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12219 mono_declsec_flags_from_method (MonoMethod *method)
12221 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12222 /* FIXME: No cache (for the moment) */
12223 guint32 idx = mono_method_get_index (method);
12224 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12225 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12226 return mono_declsec_get_flags (method->klass->image, idx);
12232 * Get the security actions (in the form of flags) associated with the specified class.
12234 * @klass: The class for which we want the declarative security flags.
12235 * Return the declarative security flags for the class.
12237 * Note: We cache the flags inside the MonoClass structure as this will get
12238 * called very often (at least for each method).
12241 mono_declsec_flags_from_class (MonoClass *klass)
12243 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12244 if (!klass->ext || !klass->ext->declsec_flags) {
12247 idx = mono_metadata_token_index (klass->type_token);
12248 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12249 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12250 mono_loader_lock ();
12251 mono_class_alloc_ext (klass);
12252 mono_loader_unlock ();
12253 /* we cache the flags on classes */
12254 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12256 return klass->ext->declsec_flags;
12262 * Get the security actions (in the form of flags) associated with the specified assembly.
12264 * @assembly: The assembly for which we want the declarative security flags.
12265 * Return the declarative security flags for the assembly.
12268 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12270 guint32 idx = 1; /* there is only one assembly */
12271 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12272 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12273 return mono_declsec_get_flags (assembly->image, idx);
12278 * Fill actions for the specific index (which may either be an encoded class token or
12279 * an encoded method token) from the metadata image.
12280 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12283 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12284 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12286 MonoBoolean result = FALSE;
12288 guint32 cols [MONO_DECL_SECURITY_SIZE];
12289 int index = mono_metadata_declsec_from_index (image, token);
12292 t = &image->tables [MONO_TABLE_DECLSECURITY];
12293 for (i = index; i < t->rows; i++) {
12294 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12296 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12299 /* if present only replace (class) permissions with method permissions */
12300 /* if empty accept either class or method permissions */
12301 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12302 if (!actions->demand.blob) {
12303 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12304 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12305 actions->demand.blob = (char*) (blob + 2);
12306 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12309 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12310 if (!actions->noncasdemand.blob) {
12311 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12312 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12313 actions->noncasdemand.blob = (char*) (blob + 2);
12314 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12317 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12318 if (!actions->demandchoice.blob) {
12319 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12320 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12321 actions->demandchoice.blob = (char*) (blob + 2);
12322 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12332 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12333 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12335 guint32 idx = mono_metadata_token_index (klass->type_token);
12336 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12337 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12338 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12342 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12343 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12345 guint32 idx = mono_method_get_index (method);
12346 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12347 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12348 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12352 * Collect all actions (that requires to generate code in mini) assigned for
12353 * the specified method.
12354 * Note: Don't use the content of actions if the function return FALSE.
12357 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12359 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12360 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12361 MonoBoolean result = FALSE;
12364 /* quick exit if no declarative security is present in the metadata */
12365 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12368 /* we want the original as the wrapper is "free" of the security informations */
12369 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12370 method = mono_marshal_method_from_wrapper (method);
12375 /* First we look for method-level attributes */
12376 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12377 mono_class_init (method->klass);
12378 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12380 result = mono_declsec_get_method_demands_params (method, demands,
12381 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12384 /* Here we use (or create) the class declarative cache to look for demands */
12385 flags = mono_declsec_flags_from_class (method->klass);
12386 if (flags & mask) {
12388 mono_class_init (method->klass);
12389 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12391 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12392 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12395 /* The boolean return value is used as a shortcut in case nothing needs to
12396 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12402 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12404 * Note: Don't use the content of actions if the function return FALSE.
12407 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12409 MonoBoolean result = FALSE;
12412 /* quick exit if no declarative security is present in the metadata */
12413 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12416 /* we want the original as the wrapper is "free" of the security informations */
12417 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12418 method = mono_marshal_method_from_wrapper (method);
12423 /* results are independant - zeroize both */
12424 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12425 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12427 /* First we look for method-level attributes */
12428 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12429 mono_class_init (method->klass);
12431 result = mono_declsec_get_method_demands_params (method, cmethod,
12432 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12435 /* Here we use (or create) the class declarative cache to look for demands */
12436 flags = mono_declsec_flags_from_class (method->klass);
12437 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12438 mono_class_init (method->klass);
12440 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12441 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12448 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12450 * @klass The inherited class - this is the class that provides the security check (attributes)
12452 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12454 * Note: Don't use the content of actions if the function return FALSE.
12457 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12459 MonoBoolean result = FALSE;
12462 /* quick exit if no declarative security is present in the metadata */
12463 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12466 /* Here we use (or create) the class declarative cache to look for demands */
12467 flags = mono_declsec_flags_from_class (klass);
12468 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12469 mono_class_init (klass);
12470 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12472 result |= mono_declsec_get_class_demands_params (klass, demands,
12473 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12480 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12482 * Note: Don't use the content of actions if the function return FALSE.
12485 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12487 /* quick exit if no declarative security is present in the metadata */
12488 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12491 /* we want the original as the wrapper is "free" of the security informations */
12492 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12493 method = mono_marshal_method_from_wrapper (method);
12498 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12499 mono_class_init (method->klass);
12500 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12502 return mono_declsec_get_method_demands_params (method, demands,
12503 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12510 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12512 guint32 cols [MONO_DECL_SECURITY_SIZE];
12516 int index = mono_metadata_declsec_from_index (image, token);
12520 t = &image->tables [MONO_TABLE_DECLSECURITY];
12521 for (i = index; i < t->rows; i++) {
12522 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12524 /* shortcut - index are ordered */
12525 if (token != cols [MONO_DECL_SECURITY_PARENT])
12528 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12529 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12530 entry->blob = (char*) (metadata + 2);
12531 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12540 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12542 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12543 guint32 idx = mono_method_get_index (method);
12544 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12545 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12546 return get_declsec_action (method->klass->image, idx, action, entry);
12552 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12555 guint32 flags = mono_declsec_flags_from_class (klass);
12556 if (declsec_flags_map [action] & flags) {
12557 guint32 idx = mono_metadata_token_index (klass->type_token);
12558 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12559 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12560 return get_declsec_action (klass->image, idx, action, entry);
12566 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12568 guint32 idx = 1; /* there is only one assembly */
12569 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12570 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12572 return get_declsec_action (assembly->image, idx, action, entry);
12576 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12578 MonoObject *res, *exc;
12580 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12581 static MonoMethod *method = NULL;
12583 if (!System_Reflection_Emit_TypeBuilder) {
12584 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12585 g_assert (System_Reflection_Emit_TypeBuilder);
12587 if (method == NULL) {
12588 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12593 * The result of mono_type_get_object () might be a System.MonoType but we
12594 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12596 g_assert (mono_class_get_ref_info (klass));
12597 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12599 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12601 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12605 return *(MonoBoolean*)mono_object_unbox (res);
12609 * mono_reflection_type_get_type:
12610 * @reftype: the System.Type object
12612 * Returns the MonoType* associated with the C# System.Type object @reftype.
12615 mono_reflection_type_get_type (MonoReflectionType *reftype)
12617 g_assert (reftype);
12619 return mono_reflection_type_get_handle (reftype);