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 p = buf = g_malloc (64);
1759 *ret_type = MONO_TYPE_CLASS;
1761 box_val = (char*)&dummy;
1763 box_val = ((char*)val) + sizeof (MonoObject);
1764 *ret_type = val->vtable->klass->byval_arg.type;
1767 switch (*ret_type) {
1768 case MONO_TYPE_BOOLEAN:
1773 case MONO_TYPE_CHAR:
1790 case MONO_TYPE_VALUETYPE: {
1791 MonoClass *klass = val->vtable->klass;
1793 if (klass->enumtype) {
1794 *ret_type = mono_class_enum_basetype (klass)->type;
1796 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1799 g_error ("we can't encode valuetypes, we should have never reached this line");
1802 case MONO_TYPE_CLASS:
1804 case MONO_TYPE_STRING: {
1805 MonoString *str = (MonoString*)val;
1806 /* there is no signature */
1807 len = str->length * 2;
1808 mono_metadata_encode_value (len, b, &b);
1809 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1811 char *swapped = g_malloc (2 * mono_string_length (str));
1812 const char *p = (const char*)mono_string_chars (str);
1814 swap_with_size (swapped, p, 2, mono_string_length (str));
1815 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1819 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1825 case MONO_TYPE_GENERICINST:
1826 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1829 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1832 /* there is no signature */
1833 mono_metadata_encode_value (len, b, &b);
1834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1835 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1836 swap_with_size (blob_size, box_val, len, 1);
1837 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1839 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1847 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1852 sigbuffer_init (&buf, 32);
1854 sigbuffer_add_value (&buf, minfo->type);
1856 switch (minfo->type) {
1857 case MONO_NATIVE_BYVALTSTR:
1858 case MONO_NATIVE_BYVALARRAY:
1859 sigbuffer_add_value (&buf, minfo->count);
1861 case MONO_NATIVE_LPARRAY:
1862 if (minfo->eltype || minfo->has_size) {
1863 sigbuffer_add_value (&buf, minfo->eltype);
1864 if (minfo->has_size) {
1865 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1866 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1868 /* LAMESPEC: ElemMult is undocumented */
1869 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1873 case MONO_NATIVE_SAFEARRAY:
1875 sigbuffer_add_value (&buf, minfo->eltype);
1877 case MONO_NATIVE_CUSTOM:
1879 str = mono_string_to_utf8 (minfo->guid);
1881 sigbuffer_add_value (&buf, len);
1882 sigbuffer_add_mem (&buf, str, len);
1885 sigbuffer_add_value (&buf, 0);
1887 /* native type name */
1888 sigbuffer_add_value (&buf, 0);
1889 /* custom marshaler type name */
1890 if (minfo->marshaltype || minfo->marshaltyperef) {
1891 if (minfo->marshaltyperef)
1892 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1894 str = mono_string_to_utf8 (minfo->marshaltype);
1896 sigbuffer_add_value (&buf, len);
1897 sigbuffer_add_mem (&buf, str, len);
1900 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1901 sigbuffer_add_value (&buf, 0);
1903 if (minfo->mcookie) {
1904 str = mono_string_to_utf8 (minfo->mcookie);
1906 sigbuffer_add_value (&buf, len);
1907 sigbuffer_add_mem (&buf, str, len);
1910 sigbuffer_add_value (&buf, 0);
1916 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1917 sigbuffer_free (&buf);
1922 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1924 MonoDynamicTable *table;
1927 /* maybe this fixup should be done in the C# code */
1928 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1929 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1930 table = &assembly->tables [MONO_TABLE_FIELD];
1931 fb->table_idx = table->next_idx ++;
1932 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1933 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1934 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1935 values [MONO_FIELD_FLAGS] = fb->attrs;
1936 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1938 if (fb->offset != -1) {
1939 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1941 alloc_table (table, table->rows);
1942 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1943 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1944 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1946 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1947 guint32 field_type = 0;
1948 table = &assembly->tables [MONO_TABLE_CONSTANT];
1950 alloc_table (table, table->rows);
1951 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1952 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1953 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1954 values [MONO_CONSTANT_TYPE] = field_type;
1955 values [MONO_CONSTANT_PADDING] = 0;
1957 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1959 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1961 alloc_table (table, table->rows);
1962 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1963 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1965 * We store it in the code section because it's simpler for now.
1968 if (mono_array_length (fb->rva_data) >= 10)
1969 stream_data_align (&assembly->code);
1970 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1972 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1973 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1975 if (fb->marshal_info) {
1976 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1978 alloc_table (table, table->rows);
1979 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1980 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1981 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1986 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1989 guint32 nparams = 0;
1990 MonoReflectionMethodBuilder *mb = fb->get_method;
1991 MonoReflectionMethodBuilder *smb = fb->set_method;
1994 if (mb && mb->parameters)
1995 nparams = mono_array_length (mb->parameters);
1996 if (!mb && smb && smb->parameters)
1997 nparams = mono_array_length (smb->parameters) - 1;
1998 sigbuffer_init (&buf, 32);
1999 if (fb->call_conv & 0x20)
2000 sigbuffer_add_byte (&buf, 0x28);
2002 sigbuffer_add_byte (&buf, 0x08);
2003 sigbuffer_add_value (&buf, nparams);
2005 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2006 for (i = 0; i < nparams; ++i) {
2007 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2008 encode_reflection_type (assembly, pt, &buf);
2010 } else if (smb && smb->parameters) {
2011 /* the property type is the last param */
2012 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2013 for (i = 0; i < nparams; ++i) {
2014 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2015 encode_reflection_type (assembly, pt, &buf);
2018 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2021 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2022 sigbuffer_free (&buf);
2027 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2029 MonoDynamicTable *table;
2031 guint num_methods = 0;
2035 * we need to set things in the following tables:
2036 * PROPERTYMAP (info already filled in _get_type_info ())
2037 * PROPERTY (rows already preallocated in _get_type_info ())
2038 * METHOD (method info already done with the generic method code)
2042 table = &assembly->tables [MONO_TABLE_PROPERTY];
2043 pb->table_idx = table->next_idx ++;
2044 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2045 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2046 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2047 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2049 /* FIXME: we still don't handle 'other' methods */
2050 if (pb->get_method) num_methods ++;
2051 if (pb->set_method) num_methods ++;
2053 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2054 table->rows += num_methods;
2055 alloc_table (table, table->rows);
2057 if (pb->get_method) {
2058 semaidx = table->next_idx ++;
2059 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2061 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2062 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2064 if (pb->set_method) {
2065 semaidx = table->next_idx ++;
2066 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2067 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2068 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2069 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2071 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2072 guint32 field_type = 0;
2073 table = &assembly->tables [MONO_TABLE_CONSTANT];
2075 alloc_table (table, table->rows);
2076 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2077 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2078 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2079 values [MONO_CONSTANT_TYPE] = field_type;
2080 values [MONO_CONSTANT_PADDING] = 0;
2085 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2087 MonoDynamicTable *table;
2089 guint num_methods = 0;
2093 * we need to set things in the following tables:
2094 * EVENTMAP (info already filled in _get_type_info ())
2095 * EVENT (rows already preallocated in _get_type_info ())
2096 * METHOD (method info already done with the generic method code)
2099 table = &assembly->tables [MONO_TABLE_EVENT];
2100 eb->table_idx = table->next_idx ++;
2101 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2102 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2103 values [MONO_EVENT_FLAGS] = eb->attrs;
2104 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2107 * FIXME: we still don't handle 'other' methods
2109 if (eb->add_method) num_methods ++;
2110 if (eb->remove_method) num_methods ++;
2111 if (eb->raise_method) num_methods ++;
2113 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2114 table->rows += num_methods;
2115 alloc_table (table, table->rows);
2117 if (eb->add_method) {
2118 semaidx = table->next_idx ++;
2119 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2121 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2122 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2124 if (eb->remove_method) {
2125 semaidx = table->next_idx ++;
2126 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2128 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2129 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2131 if (eb->raise_method) {
2132 semaidx = table->next_idx ++;
2133 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2135 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2136 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2141 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2143 MonoDynamicTable *table;
2144 guint32 num_constraints, i;
2148 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2149 num_constraints = gparam->iface_constraints ?
2150 mono_array_length (gparam->iface_constraints) : 0;
2151 table->rows += num_constraints;
2152 if (gparam->base_type)
2154 alloc_table (table, table->rows);
2156 if (gparam->base_type) {
2157 table_idx = table->next_idx ++;
2158 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2160 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2161 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2162 assembly, mono_reflection_type_get_handle (gparam->base_type));
2165 for (i = 0; i < num_constraints; i++) {
2166 MonoReflectionType *constraint = mono_array_get (
2167 gparam->iface_constraints, gpointer, i);
2169 table_idx = table->next_idx ++;
2170 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2172 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2173 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2174 assembly, mono_reflection_type_get_handle (constraint));
2179 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2181 GenericParamTableEntry *entry;
2184 * The GenericParam table must be sorted according to the `owner' field.
2185 * We need to do this sorting prior to writing the GenericParamConstraint
2186 * table, since we have to use the final GenericParam table indices there
2187 * and they must also be sorted.
2190 entry = g_new0 (GenericParamTableEntry, 1);
2191 entry->owner = owner;
2192 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2193 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2194 entry->gparam = gparam;
2196 g_ptr_array_add (assembly->gen_params, entry);
2200 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2202 MonoDynamicTable *table;
2203 MonoGenericParam *param;
2207 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2208 table_idx = table->next_idx ++;
2209 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2211 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2213 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2214 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2215 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2216 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2218 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2220 encode_constraints (entry->gparam, table_idx, assembly);
2224 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2226 MonoDynamicTable *table;
2229 guint32 cols [MONO_ASSEMBLY_SIZE];
2233 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2236 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2237 table = &assembly->tables [MONO_TABLE_MODULEREF];
2238 token = table->next_idx ++;
2240 alloc_table (table, table->rows);
2241 values = table->values + token * MONO_MODULEREF_SIZE;
2242 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2244 token <<= MONO_RESOLTION_SCOPE_BITS;
2245 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2246 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2251 if (image->assembly->dynamic)
2253 memset (cols, 0, sizeof (cols));
2255 /* image->assembly->image is the manifest module */
2256 image = image->assembly->image;
2257 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2260 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2261 token = table->next_idx ++;
2263 alloc_table (table, table->rows);
2264 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2265 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2266 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2267 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2268 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2269 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2270 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2271 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2272 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2274 if (strcmp ("", image->assembly->aname.culture)) {
2275 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2276 image->assembly->aname.culture);
2279 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2280 guchar pubtoken [9];
2282 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2283 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2285 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2287 token <<= MONO_RESOLTION_SCOPE_BITS;
2288 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2289 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2294 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2296 MonoDynamicTable *table;
2301 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2304 sigbuffer_init (&buf, 32);
2305 switch (type->type) {
2306 case MONO_TYPE_FNPTR:
2308 case MONO_TYPE_SZARRAY:
2309 case MONO_TYPE_ARRAY:
2311 case MONO_TYPE_MVAR:
2312 case MONO_TYPE_GENERICINST:
2313 encode_type (assembly, type, &buf);
2315 case MONO_TYPE_CLASS:
2316 case MONO_TYPE_VALUETYPE: {
2317 MonoClass *k = mono_class_from_mono_type (type);
2318 if (!k || !k->generic_container) {
2319 sigbuffer_free (&buf);
2322 encode_type (assembly, type, &buf);
2326 sigbuffer_free (&buf);
2330 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2331 if (assembly->save) {
2332 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2333 alloc_table (table, table->rows + 1);
2334 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2335 values [MONO_TYPESPEC_SIGNATURE] = token;
2337 sigbuffer_free (&buf);
2339 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2340 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2346 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2348 MonoDynamicTable *table;
2350 guint32 token, scope, enclosing;
2353 /* if the type requires a typespec, we must try that first*/
2354 if (try_typespec && (token = create_typespec (assembly, type)))
2356 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2359 klass = mono_class_from_mono_type (type);
2361 klass = mono_class_from_mono_type (type);
2364 * If it's in the same module and not a generic type parameter:
2366 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2367 (type->type != MONO_TYPE_MVAR)) {
2368 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2369 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2370 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2374 if (klass->nested_in) {
2375 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2376 /* get the typeref idx of the enclosing type */
2377 enclosing >>= MONO_TYPEDEFORREF_BITS;
2378 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2380 scope = resolution_scope_from_image (assembly, klass->image);
2382 table = &assembly->tables [MONO_TABLE_TYPEREF];
2383 if (assembly->save) {
2384 alloc_table (table, table->rows + 1);
2385 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2386 values [MONO_TYPEREF_SCOPE] = scope;
2387 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2388 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2390 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2391 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2393 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2398 * Despite the name, we handle also TypeSpec (with the above helper).
2401 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2403 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2406 #ifndef DISABLE_REFLECTION_EMIT
2408 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2410 MonoDynamicTable *table;
2412 guint32 token, pclass;
2414 switch (parent & MONO_TYPEDEFORREF_MASK) {
2415 case MONO_TYPEDEFORREF_TYPEREF:
2416 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2418 case MONO_TYPEDEFORREF_TYPESPEC:
2419 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2421 case MONO_TYPEDEFORREF_TYPEDEF:
2422 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2425 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2428 /* extract the index */
2429 parent >>= MONO_TYPEDEFORREF_BITS;
2431 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2433 if (assembly->save) {
2434 alloc_table (table, table->rows + 1);
2435 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2436 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2437 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2438 values [MONO_MEMBERREF_SIGNATURE] = sig;
2441 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2448 * Insert a memberef row into the metadata: the token that point to the memberref
2449 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2450 * mono_image_get_fieldref_token()).
2451 * The sig param is an index to an already built signature.
2454 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2456 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2457 return mono_image_add_memberef_row (assembly, parent, name, sig);
2462 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2465 MonoMethodSignature *sig;
2467 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2469 if (create_typespec) {
2470 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2475 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2476 if (token && !create_typespec)
2479 g_assert (!method->is_inflated);
2482 * A methodref signature can't contain an unmanaged calling convention.
2484 sig = mono_metadata_signature_dup (mono_method_signature (method));
2485 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2486 sig->call_convention = MONO_CALL_DEFAULT;
2487 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2488 method->name, method_encode_signature (assembly, sig));
2490 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2493 if (create_typespec) {
2494 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2495 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2496 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2498 if (assembly->save) {
2501 alloc_table (table, table->rows + 1);
2502 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2503 values [MONO_METHODSPEC_METHOD] = token;
2504 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2507 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2509 /*methodspec and memberef tokens are diferent, */
2510 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2517 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2519 guint32 token, parent, sig;
2520 ReflectionMethodBuilder rmb;
2522 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2524 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2528 name = mono_string_to_utf8 (method->name);
2529 reflection_methodbuilder_from_method_builder (&rmb, method);
2532 * A methodref signature can't contain an unmanaged calling convention.
2533 * Since some flags are encoded as part of call_conv, we need to check against it.
2535 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2536 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2538 sig = method_builder_encode_signature (assembly, &rmb);
2540 if (tb->generic_params)
2541 parent = create_generic_typespec (assembly, tb);
2543 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2545 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2548 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2553 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2554 const gchar *name, guint32 sig)
2556 MonoDynamicTable *table;
2560 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2562 if (assembly->save) {
2563 alloc_table (table, table->rows + 1);
2564 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2565 values [MONO_MEMBERREF_CLASS] = original;
2566 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2567 values [MONO_MEMBERREF_SIGNATURE] = sig;
2570 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2577 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2581 guint32 nparams = mono_array_length (mb->generic_params);
2584 if (!assembly->save)
2587 sigbuffer_init (&buf, 32);
2589 sigbuffer_add_value (&buf, 0xa);
2590 sigbuffer_add_value (&buf, nparams);
2592 for (i = 0; i < nparams; i++) {
2593 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2594 sigbuffer_add_value (&buf, i);
2597 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2598 sigbuffer_free (&buf);
2603 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2605 MonoDynamicTable *table;
2607 guint32 token, mtoken = 0;
2609 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2613 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2615 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2616 switch (mono_metadata_token_table (mtoken)) {
2617 case MONO_TABLE_MEMBERREF:
2618 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2620 case MONO_TABLE_METHOD:
2621 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2624 g_assert_not_reached ();
2627 if (assembly->save) {
2628 alloc_table (table, table->rows + 1);
2629 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2630 values [MONO_METHODSPEC_METHOD] = mtoken;
2631 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2634 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2637 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2642 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2646 if (mb->generic_params && create_methodspec)
2647 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2649 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2653 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2654 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2659 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2661 guint32 token, parent, sig;
2662 ReflectionMethodBuilder rmb;
2664 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2666 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2670 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2672 if (tb->generic_params)
2673 parent = create_generic_typespec (assembly, tb);
2675 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2677 name = mono_string_to_utf8 (rmb.name);
2678 sig = method_builder_encode_signature (assembly, &rmb);
2680 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2683 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2689 is_field_on_inst (MonoClassField *field)
2691 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2695 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2698 get_field_on_inst_generic_type (MonoClassField *field)
2700 MonoClass *class, *gtd;
2701 MonoDynamicGenericClass *dgclass;
2704 g_assert (is_field_on_inst (field));
2706 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2708 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2709 field_index = field - dgclass->fields;
2710 return dgclass->field_generic_types [field_index];
2713 class = field->parent;
2714 gtd = class->generic_class->container_class;
2716 if (field >= class->fields && field - class->fields < class->field.count) {
2717 field_index = field - class->fields;
2718 return gtd->fields [field_index].type;
2721 g_assert_not_reached ();
2725 #ifndef DISABLE_REFLECTION_EMIT
2727 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2733 g_assert (field->parent);
2735 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2739 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2740 int index = field - field->parent->fields;
2741 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2743 if (is_field_on_inst (field))
2744 type = get_field_on_inst_generic_type (field);
2746 type = mono_field_get_type (field);
2748 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2749 mono_field_get_name (field),
2750 fieldref_encode_signature (assembly, field->parent->image, type));
2751 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2756 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2760 MonoGenericClass *gclass;
2761 MonoDynamicGenericClass *dgclass;
2765 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2768 if (is_sre_field_builder (mono_object_class (f->fb))) {
2769 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2770 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2771 klass = mono_class_from_mono_type (type);
2772 gclass = type->data.generic_class;
2773 g_assert (gclass->is_dynamic);
2774 dgclass = (MonoDynamicGenericClass *) gclass;
2776 name = mono_string_to_utf8 (fb->name);
2777 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2778 field_encode_signature (assembly, fb));
2780 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2782 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2784 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785 klass = mono_class_from_mono_type (type);
2787 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2788 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2790 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2791 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2794 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2799 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2803 MonoGenericClass *gclass;
2806 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2808 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2812 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2813 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2814 MonoDynamicGenericClass *dgclass;
2815 ReflectionMethodBuilder rmb;
2818 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819 klass = mono_class_from_mono_type (type);
2821 gclass = type->data.generic_class;
2822 g_assert (gclass->is_dynamic);
2823 dgclass = (MonoDynamicGenericClass *) gclass;
2825 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2827 name = mono_string_to_utf8 (rmb.name);
2829 sig = method_builder_encode_signature (assembly, &rmb);
2831 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2833 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2834 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2836 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2837 klass = mono_class_from_mono_type (type);
2839 sig = method_encode_signature (assembly, mono_method_signature (mm));
2840 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2842 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2843 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2847 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2852 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2855 MonoGenericContext tmp_context;
2856 MonoType **type_argv;
2857 MonoGenericInst *ginst;
2858 MonoMethod *method, *inflated;
2861 init_type_builder_generics ((MonoObject*)m->inst);
2863 method = inflate_method (m->inst, (MonoObject*)m->mb);
2865 klass = method->klass;
2867 if (m->method_args == NULL)
2870 if (method->is_inflated)
2871 method = ((MonoMethodInflated *) method)->declaring;
2873 count = mono_array_length (m->method_args);
2875 type_argv = g_new0 (MonoType *, count);
2876 for (i = 0; i < count; i++) {
2877 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2878 type_argv [i] = mono_reflection_type_get_handle (garg);
2880 ginst = mono_metadata_get_generic_inst (count, type_argv);
2883 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2884 tmp_context.method_inst = ginst;
2886 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2891 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2893 guint32 sig, token = 0;
2897 if (m->method_args) {
2898 MonoMethod *inflated;
2900 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2901 if (create_methodspec)
2902 token = mono_image_get_methodspec_token (assembly, inflated);
2904 token = mono_image_get_inflated_method_token (assembly, inflated);
2908 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2912 if (is_sre_method_builder (mono_object_class (m->mb))) {
2913 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2914 MonoGenericClass *gclass;
2915 ReflectionMethodBuilder rmb;
2918 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2919 klass = mono_class_from_mono_type (type);
2920 gclass = type->data.generic_class;
2921 g_assert (gclass->is_dynamic);
2923 reflection_methodbuilder_from_method_builder (&rmb, mb);
2925 name = mono_string_to_utf8 (rmb.name);
2927 sig = method_builder_encode_signature (assembly, &rmb);
2929 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2931 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2932 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2934 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2935 klass = mono_class_from_mono_type (type);
2937 sig = method_encode_signature (assembly, mono_method_signature (mm));
2938 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2940 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2941 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2944 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2949 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2953 guint32 nparams = context->method_inst->type_argc;
2956 if (!assembly->save)
2959 sigbuffer_init (&buf, 32);
2961 * FIXME: vararg, explicit_this, differenc call_conv values...
2963 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2964 sigbuffer_add_value (&buf, nparams);
2966 for (i = 0; i < nparams; i++)
2967 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2969 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2970 sigbuffer_free (&buf);
2975 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2977 MonoDynamicTable *table;
2979 guint32 token, mtoken = 0, sig;
2980 MonoMethodInflated *imethod;
2981 MonoMethod *declaring;
2983 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2985 g_assert (method->is_inflated);
2986 imethod = (MonoMethodInflated *) method;
2987 declaring = imethod->declaring;
2989 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2990 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2992 if (!mono_method_signature (declaring)->generic_param_count)
2995 switch (mono_metadata_token_table (mtoken)) {
2996 case MONO_TABLE_MEMBERREF:
2997 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2999 case MONO_TABLE_METHOD:
3000 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3003 g_assert_not_reached ();
3006 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3008 if (assembly->save) {
3009 alloc_table (table, table->rows + 1);
3010 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3011 values [MONO_METHODSPEC_METHOD] = mtoken;
3012 values [MONO_METHODSPEC_SIGNATURE] = sig;
3015 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3022 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3024 MonoMethodInflated *imethod;
3027 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3031 g_assert (method->is_inflated);
3032 imethod = (MonoMethodInflated *) method;
3034 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3035 token = method_encode_methodspec (assembly, method);
3037 guint32 sig = method_encode_signature (
3038 assembly, mono_method_signature (imethod->declaring));
3039 token = mono_image_get_memberref_token (
3040 assembly, &method->klass->byval_arg, method->name, sig);
3043 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3048 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3050 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3053 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3054 token = mono_image_get_memberref_token (
3055 assembly, &m->klass->byval_arg, m->name, sig);
3061 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3063 MonoDynamicTable *table;
3072 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3073 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3074 * Because of this, we must not insert it into the `typeref' hash table.
3076 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3077 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3081 sigbuffer_init (&buf, 32);
3083 g_assert (tb->generic_params);
3084 klass = mono_class_from_mono_type (type);
3086 if (tb->generic_container)
3087 mono_reflection_create_generic_class (tb);
3089 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3090 g_assert (klass->generic_container);
3091 sigbuffer_add_value (&buf, klass->byval_arg.type);
3092 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3094 count = mono_array_length (tb->generic_params);
3095 sigbuffer_add_value (&buf, count);
3096 for (i = 0; i < count; i++) {
3097 MonoReflectionGenericParam *gparam;
3099 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3101 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3104 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3106 if (assembly->save) {
3107 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3108 alloc_table (table, table->rows + 1);
3109 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3110 values [MONO_TYPESPEC_SIGNATURE] = token;
3112 sigbuffer_free (&buf);
3114 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3115 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3121 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3124 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3126 int i, count, len, pos;
3131 count += mono_array_length (modreq);
3133 count += mono_array_length (modopt);
3136 return mono_metadata_type_dup (NULL, type);
3138 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3140 memcpy (t, type, MONO_SIZEOF_TYPE);
3142 t->num_mods = count;
3145 for (i = 0; i < mono_array_length (modreq); ++i) {
3146 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3147 t->modifiers [pos].required = 1;
3148 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3153 for (i = 0; i < mono_array_length (modopt); ++i) {
3154 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3155 t->modifiers [pos].required = 0;
3156 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3165 init_type_builder_generics (MonoObject *type)
3167 MonoReflectionTypeBuilder *tb;
3169 if (!is_sre_type_builder(mono_object_class (type)))
3171 tb = (MonoReflectionTypeBuilder *)type;
3173 if (tb && tb->generic_container)
3174 mono_reflection_create_generic_class (tb);
3178 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3180 MonoDynamicTable *table;
3182 MonoType *custom = NULL, *type;
3184 guint32 token, pclass, parent, sig;
3187 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3191 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3192 name = mono_string_to_utf8 (fb->name);
3194 /*FIXME this is one more layer of ugliness due how types are created.*/
3195 init_type_builder_generics (fb->type);
3197 /* fb->type does not include the custom modifiers */
3198 /* FIXME: We should do this in one place when a fieldbuilder is created */
3199 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3200 if (fb->modreq || fb->modopt)
3201 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3203 sig = fieldref_encode_signature (assembly, NULL, type);
3206 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3207 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3209 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3210 parent >>= MONO_TYPEDEFORREF_BITS;
3212 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3214 if (assembly->save) {
3215 alloc_table (table, table->rows + 1);
3216 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3217 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3218 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3219 values [MONO_MEMBERREF_SIGNATURE] = sig;
3222 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3224 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3230 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3237 if (!assembly->save)
3240 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3241 g_assert (helper->type == 2);
3243 if (helper->arguments)
3244 nargs = mono_array_length (helper->arguments);
3248 size = 10 + (nargs * 10);
3250 sigbuffer_init (&buf, 32);
3252 /* Encode calling convention */
3253 /* Change Any to Standard */
3254 if ((helper->call_conv & 0x03) == 0x03)
3255 helper->call_conv = 0x01;
3256 /* explicit_this implies has_this */
3257 if (helper->call_conv & 0x40)
3258 helper->call_conv &= 0x20;
3260 if (helper->call_conv == 0) { /* Unmanaged */
3261 idx = helper->unmanaged_call_conv - 1;
3264 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3265 if (helper->call_conv & 0x02) /* varargs */
3269 sigbuffer_add_byte (&buf, idx);
3270 sigbuffer_add_value (&buf, nargs);
3271 encode_reflection_type (assembly, helper->return_type, &buf);
3272 for (i = 0; i < nargs; ++i) {
3273 MonoArray *modreqs = NULL;
3274 MonoArray *modopts = NULL;
3275 MonoReflectionType *pt;
3277 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3278 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3279 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3280 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3282 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3283 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3284 encode_reflection_type (assembly, pt, &buf);
3286 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287 sigbuffer_free (&buf);
3293 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3296 MonoDynamicTable *table;
3299 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3300 idx = table->next_idx ++;
3302 alloc_table (table, table->rows);
3303 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3305 values [MONO_STAND_ALONE_SIGNATURE] =
3306 mono_reflection_encode_sighelper (assembly, helper);
3312 reflection_cc_to_file (int call_conv) {
3313 switch (call_conv & 0x3) {
3315 case 1: return MONO_CALL_DEFAULT;
3316 case 2: return MONO_CALL_VARARG;
3318 g_assert_not_reached ();
3322 #endif /* !DISABLE_REFLECTION_EMIT */
3326 MonoMethodSignature *sig;
3331 #ifndef DISABLE_REFLECTION_EMIT
3333 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3338 MonoMethodSignature *sig;
3342 name = mono_string_to_utf8 (m->name);
3343 nparams = mono_array_length (m->parameters);
3344 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3346 sig->sentinelpos = -1;
3347 sig->call_convention = reflection_cc_to_file (m->call_conv);
3348 sig->param_count = nparams;
3349 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3350 mtype = mono_reflection_type_get_handle (m->parent);
3351 for (i = 0; i < nparams; ++i)
3352 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3354 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3356 if (strcmp (name, am->name) == 0 &&
3357 mono_metadata_type_equal (am->parent, mtype) &&
3358 mono_metadata_signature_equal (am->sig, sig)) {
3361 m->table_idx = am->token & 0xffffff;
3365 am = g_new0 (ArrayMethod, 1);
3369 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3370 method_encode_signature (assembly, sig));
3371 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3372 m->table_idx = am->token & 0xffffff;
3377 * Insert into the metadata tables all the info about the TypeBuilder tb.
3378 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3381 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3383 MonoDynamicTable *table;
3385 int i, is_object = 0, is_system = 0;
3388 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3389 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3390 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3391 n = mono_string_to_utf8 (tb->name);
3392 if (strcmp (n, "Object") == 0)
3394 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3396 n = mono_string_to_utf8 (tb->nspace);
3397 if (strcmp (n, "System") == 0)
3399 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3401 if (tb->parent && !(is_system && is_object) &&
3402 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3403 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3405 values [MONO_TYPEDEF_EXTENDS] = 0;
3407 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3408 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3411 * if we have explicitlayout or sequentiallayouts, output data in the
3412 * ClassLayout table.
3414 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3415 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3416 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3418 alloc_table (table, table->rows);
3419 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3420 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3421 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3422 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3425 /* handle interfaces */
3426 if (tb->interfaces) {
3427 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3429 table->rows += mono_array_length (tb->interfaces);
3430 alloc_table (table, table->rows);
3431 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3432 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3433 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3434 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3435 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3436 values += MONO_INTERFACEIMPL_SIZE;
3442 table = &assembly->tables [MONO_TABLE_FIELD];
3443 table->rows += tb->num_fields;
3444 alloc_table (table, table->rows);
3445 for (i = 0; i < tb->num_fields; ++i)
3446 mono_image_get_field_info (
3447 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3450 /* handle constructors */
3452 table = &assembly->tables [MONO_TABLE_METHOD];
3453 table->rows += mono_array_length (tb->ctors);
3454 alloc_table (table, table->rows);
3455 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3456 mono_image_get_ctor_info (domain,
3457 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3460 /* handle methods */
3462 table = &assembly->tables [MONO_TABLE_METHOD];
3463 table->rows += tb->num_methods;
3464 alloc_table (table, table->rows);
3465 for (i = 0; i < tb->num_methods; ++i)
3466 mono_image_get_method_info (
3467 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3470 /* Do the same with properties etc.. */
3471 if (tb->events && mono_array_length (tb->events)) {
3472 table = &assembly->tables [MONO_TABLE_EVENT];
3473 table->rows += mono_array_length (tb->events);
3474 alloc_table (table, table->rows);
3475 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3477 alloc_table (table, table->rows);
3478 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3479 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3480 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3481 for (i = 0; i < mono_array_length (tb->events); ++i)
3482 mono_image_get_event_info (
3483 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3485 if (tb->properties && mono_array_length (tb->properties)) {
3486 table = &assembly->tables [MONO_TABLE_PROPERTY];
3487 table->rows += mono_array_length (tb->properties);
3488 alloc_table (table, table->rows);
3489 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3491 alloc_table (table, table->rows);
3492 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3493 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3494 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3495 for (i = 0; i < mono_array_length (tb->properties); ++i)
3496 mono_image_get_property_info (
3497 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3500 /* handle generic parameters */
3501 if (tb->generic_params) {
3502 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3503 table->rows += mono_array_length (tb->generic_params);
3504 alloc_table (table, table->rows);
3505 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3506 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3508 mono_image_get_generic_param_info (
3509 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3513 mono_image_add_decl_security (assembly,
3514 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3517 MonoDynamicTable *ntable;
3519 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520 ntable->rows += mono_array_length (tb->subtypes);
3521 alloc_table (ntable, ntable->rows);
3522 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3524 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3525 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3527 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3528 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3529 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3530 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3531 mono_string_to_utf8 (tb->name), tb->table_idx,
3532 ntable->next_idx, ntable->rows);*/
3533 values += MONO_NESTED_CLASS_SIZE;
3541 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3545 mono_ptr_array_append (*types, type);
3547 if (!type->subtypes)
3550 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3551 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3552 collect_types (types, subtype);
3557 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3559 if ((*type1)->table_idx < (*type2)->table_idx)
3562 if ((*type1)->table_idx > (*type2)->table_idx)
3569 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3574 for (i = 0; i < mono_array_length (pinfo); ++i) {
3575 MonoReflectionParamBuilder *pb;
3576 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3579 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3584 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3587 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3589 for (i = 0; i < tb->num_fields; ++i) {
3590 MonoReflectionFieldBuilder* fb;
3591 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3592 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3596 for (i = 0; i < mono_array_length (tb->events); ++i) {
3597 MonoReflectionEventBuilder* eb;
3598 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3599 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3602 if (tb->properties) {
3603 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3604 MonoReflectionPropertyBuilder* pb;
3605 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3606 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3610 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3611 MonoReflectionCtorBuilder* cb;
3612 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3613 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3614 params_add_cattrs (assembly, cb->pinfo);
3619 for (i = 0; i < tb->num_methods; ++i) {
3620 MonoReflectionMethodBuilder* mb;
3621 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3622 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3623 params_add_cattrs (assembly, mb->pinfo);
3628 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3629 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3634 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3638 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3640 if (moduleb->global_methods) {
3641 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3642 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3643 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3644 params_add_cattrs (assembly, mb->pinfo);
3648 if (moduleb->global_fields) {
3649 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3650 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3651 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3655 if (moduleb->types) {
3656 for (i = 0; i < moduleb->num_types; ++i)
3657 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3662 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3664 MonoDynamicTable *table;
3668 char *b = blob_size;
3671 table = &assembly->tables [MONO_TABLE_FILE];
3673 alloc_table (table, table->rows);
3674 values = table->values + table->next_idx * MONO_FILE_SIZE;
3675 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3676 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3677 if (module->image->dynamic) {
3678 /* This depends on the fact that the main module is emitted last */
3679 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3680 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3683 path = g_strdup (module->image->name);
3685 mono_sha1_get_digest_from_file (path, hash);
3688 mono_metadata_encode_value (20, b, &b);
3689 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3695 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3697 MonoDynamicTable *table;
3700 table = &assembly->tables [MONO_TABLE_MODULE];
3701 mb->table_idx = table->next_idx ++;
3702 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3703 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3706 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3707 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3708 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3709 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3713 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3714 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3716 MonoDynamicTable *table;
3720 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3721 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3724 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3726 alloc_table (table, table->rows);
3727 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3729 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3730 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3731 if (klass->nested_in)
3732 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3734 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3735 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3736 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3738 res = table->next_idx;
3742 /* Emit nested types */
3743 if (klass->ext && klass->ext->nested_classes) {
3746 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3747 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3754 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3755 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3760 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3762 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3764 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3765 parent_index, assembly);
3769 * We need to do this ourselves since klass->nested_classes is not set up.
3772 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3773 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3778 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3779 guint32 module_index, MonoDynamicImage *assembly)
3781 MonoImage *image = module->image;
3785 t = &image->tables [MONO_TABLE_TYPEDEF];
3787 for (i = 0; i < t->rows; ++i) {
3788 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3790 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3791 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3796 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3798 MonoDynamicTable *table;
3800 guint32 scope, scope_idx, impl, current_idx;
3801 gboolean forwarder = TRUE;
3802 gpointer iter = NULL;
3805 if (klass->nested_in) {
3806 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3809 scope = resolution_scope_from_image (assembly, klass->image);
3810 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3811 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3812 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3815 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3818 alloc_table (table, table->rows);
3819 current_idx = table->next_idx;
3820 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3822 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3823 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3824 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3825 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3826 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3830 while ((nested = mono_class_get_nested_types (klass, &iter)))
3831 add_exported_type (assemblyb, assembly, nested, current_idx);
3835 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3840 if (!assemblyb->type_forwarders)
3843 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3844 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3849 type = mono_reflection_type_get_handle (t);
3852 klass = mono_class_from_mono_type (type);
3854 add_exported_type (assemblyb, assembly, klass, 0);
3858 #define align_pointer(base,p)\
3860 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3862 (p) += 4 - (__diff & 3);\
3866 compare_constants (const void *a, const void *b)
3868 const guint32 *a_values = a;
3869 const guint32 *b_values = b;
3870 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3874 compare_semantics (const void *a, const void *b)
3876 const guint32 *a_values = a;
3877 const guint32 *b_values = b;
3878 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3881 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3885 compare_custom_attrs (const void *a, const void *b)
3887 const guint32 *a_values = a;
3888 const guint32 *b_values = b;
3890 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3894 compare_field_marshal (const void *a, const void *b)
3896 const guint32 *a_values = a;
3897 const guint32 *b_values = b;
3899 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3903 compare_nested (const void *a, const void *b)
3905 const guint32 *a_values = a;
3906 const guint32 *b_values = b;
3908 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3912 compare_genericparam (const void *a, const void *b)
3914 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3915 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3917 if ((*b_entry)->owner == (*a_entry)->owner)
3919 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3920 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3922 return (*a_entry)->owner - (*b_entry)->owner;
3926 compare_declsecurity_attrs (const void *a, const void *b)
3928 const guint32 *a_values = a;
3929 const guint32 *b_values = b;
3931 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3935 compare_interface_impl (const void *a, const void *b)
3937 const guint32 *a_values = a;
3938 const guint32 *b_values = b;
3940 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3944 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3948 pad_heap (MonoDynamicStream *sh)
3950 if (sh->index & 3) {
3951 int sz = 4 - (sh->index & 3);
3952 memset (sh->data + sh->index, 0, sz);
3959 MonoDynamicStream *stream;
3963 * build_compressed_metadata() fills in the blob of data that represents the
3964 * raw metadata as it will be saved in the PE file. The five streams are output
3965 * and the metadata tables are comnpressed from the guint32 array representation,
3966 * to the compressed on-disk format.
3969 build_compressed_metadata (MonoDynamicImage *assembly)
3971 MonoDynamicTable *table;
3973 guint64 valid_mask = 0;
3974 guint64 sorted_mask;
3975 guint32 heapt_size = 0;
3976 guint32 meta_size = 256; /* allow for header and other stuff */
3977 guint32 table_offset;
3978 guint32 ntables = 0;
3984 struct StreamDesc stream_desc [5];
3986 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3987 for (i = 0; i < assembly->gen_params->len; i++){
3988 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3989 write_generic_param_entry (assembly, entry);
3992 stream_desc [0].name = "#~";
3993 stream_desc [0].stream = &assembly->tstream;
3994 stream_desc [1].name = "#Strings";
3995 stream_desc [1].stream = &assembly->sheap;
3996 stream_desc [2].name = "#US";
3997 stream_desc [2].stream = &assembly->us;
3998 stream_desc [3].name = "#Blob";
3999 stream_desc [3].stream = &assembly->blob;
4000 stream_desc [4].name = "#GUID";
4001 stream_desc [4].stream = &assembly->guid;
4003 /* tables that are sorted */
4004 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4005 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4006 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4007 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4008 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4009 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4010 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4012 /* Compute table sizes */
4013 /* the MonoImage has already been created in mono_image_basic_init() */
4014 meta = &assembly->image;
4016 /* sizes should be multiple of 4 */
4017 pad_heap (&assembly->blob);
4018 pad_heap (&assembly->guid);
4019 pad_heap (&assembly->sheap);
4020 pad_heap (&assembly->us);
4022 /* Setup the info used by compute_sizes () */
4023 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4024 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4025 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4027 meta_size += assembly->blob.index;
4028 meta_size += assembly->guid.index;
4029 meta_size += assembly->sheap.index;
4030 meta_size += assembly->us.index;
4032 for (i=0; i < MONO_TABLE_NUM; ++i)
4033 meta->tables [i].rows = assembly->tables [i].rows;
4035 for (i = 0; i < MONO_TABLE_NUM; i++){
4036 if (meta->tables [i].rows == 0)
4038 valid_mask |= (guint64)1 << i;
4040 meta->tables [i].row_size = mono_metadata_compute_size (
4041 meta, i, &meta->tables [i].size_bitfield);
4042 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4044 heapt_size += 24; /* #~ header size */
4045 heapt_size += ntables * 4;
4046 /* make multiple of 4 */
4049 meta_size += heapt_size;
4050 meta->raw_metadata = g_malloc0 (meta_size);
4051 p = (unsigned char*)meta->raw_metadata;
4052 /* the metadata signature */
4053 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4054 /* version numbers and 4 bytes reserved */
4055 int16val = (guint16*)p;
4056 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4057 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4059 /* version string */
4060 int32val = (guint32*)p;
4061 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4063 memcpy (p, meta->version, strlen (meta->version));
4064 p += GUINT32_FROM_LE (*int32val);
4065 align_pointer (meta->raw_metadata, p);
4066 int16val = (guint16*)p;
4067 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4068 *int16val = GUINT16_TO_LE (5); /* number of streams */
4072 * write the stream info.
4074 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4075 table_offset += 3; table_offset &= ~3;
4077 assembly->tstream.index = heapt_size;
4078 for (i = 0; i < 5; ++i) {
4079 int32val = (guint32*)p;
4080 stream_desc [i].stream->offset = table_offset;
4081 *int32val++ = GUINT32_TO_LE (table_offset);
4082 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4083 table_offset += GUINT32_FROM_LE (*int32val);
4084 table_offset += 3; table_offset &= ~3;
4086 strcpy ((char*)p, stream_desc [i].name);
4087 p += strlen (stream_desc [i].name) + 1;
4088 align_pointer (meta->raw_metadata, p);
4091 * now copy the data, the table stream header and contents goes first.
4093 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4094 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4095 int32val = (guint32*)p;
4096 *int32val = GUINT32_TO_LE (0); /* reserved */
4099 *p++ = 2; /* version */
4102 if (meta->idx_string_wide)
4104 if (meta->idx_guid_wide)
4106 if (meta->idx_blob_wide)
4109 *p++ = 1; /* reserved */
4110 int64val = (guint64*)p;
4111 *int64val++ = GUINT64_TO_LE (valid_mask);
4112 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4114 int32val = (guint32*)p;
4115 for (i = 0; i < MONO_TABLE_NUM; i++){
4116 if (meta->tables [i].rows == 0)
4118 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4120 p = (unsigned char*)int32val;
4122 /* sort the tables that still need sorting */
4123 table = &assembly->tables [MONO_TABLE_CONSTANT];
4125 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4126 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4128 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4129 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4131 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4132 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4134 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4135 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4137 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4138 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4139 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4141 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4142 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4144 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4146 /* compress the tables */
4147 for (i = 0; i < MONO_TABLE_NUM; i++){
4150 guint32 bitfield = meta->tables [i].size_bitfield;
4151 if (!meta->tables [i].rows)
4153 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4154 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4155 meta->tables [i].base = (char*)p;
4156 for (row = 1; row <= meta->tables [i].rows; ++row) {
4157 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4158 for (col = 0; col < assembly->tables [i].columns; ++col) {
4159 switch (mono_metadata_table_size (bitfield, col)) {
4161 *p++ = values [col];
4164 *p++ = values [col] & 0xff;
4165 *p++ = (values [col] >> 8) & 0xff;
4168 *p++ = values [col] & 0xff;
4169 *p++ = (values [col] >> 8) & 0xff;
4170 *p++ = (values [col] >> 16) & 0xff;
4171 *p++ = (values [col] >> 24) & 0xff;
4174 g_assert_not_reached ();
4178 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4181 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4182 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4183 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4184 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4185 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4187 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4191 * Some tables in metadata need to be sorted according to some criteria, but
4192 * when methods and fields are first created with reflection, they may be assigned a token
4193 * that doesn't correspond to the final token they will get assigned after the sorting.
4194 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4195 * with the reflection objects that represent them. Once all the tables are set up, the
4196 * reflection objects will contains the correct table index. fixup_method() will fixup the
4197 * tokens for the method with ILGenerator @ilgen.
4200 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4202 guint32 code_idx = GPOINTER_TO_UINT (value);
4203 MonoReflectionILTokenInfo *iltoken;
4204 MonoReflectionFieldBuilder *field;
4205 MonoReflectionCtorBuilder *ctor;
4206 MonoReflectionMethodBuilder *method;
4207 MonoReflectionTypeBuilder *tb;
4208 MonoReflectionArrayMethod *am;
4210 unsigned char *target;
4212 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4213 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4214 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4215 switch (target [3]) {
4216 case MONO_TABLE_FIELD:
4217 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4218 field = (MonoReflectionFieldBuilder *)iltoken->member;
4219 idx = field->table_idx;
4220 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4221 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4222 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4224 g_assert_not_reached ();
4227 case MONO_TABLE_METHOD:
4228 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4229 method = (MonoReflectionMethodBuilder *)iltoken->member;
4230 idx = method->table_idx;
4231 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4233 idx = ctor->table_idx;
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4235 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4236 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4237 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4239 g_assert_not_reached ();
4242 case MONO_TABLE_TYPEDEF:
4243 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4244 g_assert_not_reached ();
4245 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4246 idx = tb->table_idx;
4248 case MONO_TABLE_MEMBERREF:
4249 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4250 am = (MonoReflectionArrayMethod*)iltoken->member;
4251 idx = am->table_idx;
4252 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4253 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4254 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4255 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4256 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4257 g_assert (m->klass->generic_class || m->klass->generic_container);
4259 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4261 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4262 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4263 g_assert (is_field_on_inst (f));
4265 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4266 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4268 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4270 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4272 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4275 g_assert_not_reached ();
4278 case MONO_TABLE_METHODSPEC:
4279 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4280 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281 g_assert (mono_method_signature (m)->generic_param_count);
4283 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4285 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4288 g_assert_not_reached ();
4292 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4294 target [0] = idx & 0xff;
4295 target [1] = (idx >> 8) & 0xff;
4296 target [2] = (idx >> 16) & 0xff;
4303 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4304 * value is not known when the table is emitted.
4307 fixup_cattrs (MonoDynamicImage *assembly)
4309 MonoDynamicTable *table;
4311 guint32 type, i, idx, token;
4314 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4316 for (i = 0; i < table->rows; ++i) {
4317 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4319 type = values [MONO_CUSTOM_ATTR_TYPE];
4320 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4321 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4322 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4323 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4326 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4327 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4328 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4329 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4330 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4331 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4332 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4333 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4340 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4342 MonoDynamicTable *table;
4345 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4347 alloc_table (table, table->rows);
4348 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4349 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4350 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4351 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4352 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4357 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4359 MonoDynamicTable *table;
4363 char *b = blob_size;
4365 guint32 idx, offset;
4367 if (rsrc->filename) {
4368 name = mono_string_to_utf8 (rsrc->filename);
4369 sname = g_path_get_basename (name);
4371 table = &assembly->tables [MONO_TABLE_FILE];
4373 alloc_table (table, table->rows);
4374 values = table->values + table->next_idx * MONO_FILE_SIZE;
4375 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4376 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4379 mono_sha1_get_digest_from_file (name, hash);
4380 mono_metadata_encode_value (20, b, &b);
4381 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4382 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4384 idx = table->next_idx++;
4386 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4392 data = mono_array_addr (rsrc->data, char, 0);
4393 len = mono_array_length (rsrc->data);
4399 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4400 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4401 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4402 mono_image_add_stream_data (&assembly->resources, data, len);
4406 * The entry should be emitted into the MANIFESTRESOURCE table of
4407 * the main module, but that needs to reference the FILE table
4408 * which isn't emitted yet.
4415 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4419 set_version_from_string (MonoString *version, guint32 *values)
4421 gchar *ver, *p, *str;
4424 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4425 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4426 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4427 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4430 ver = str = mono_string_to_utf8 (version);
4431 for (i = 0; i < 4; ++i) {
4432 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4438 /* handle Revision and Build */
4448 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4452 char *b = blob_size;
4457 len = mono_array_length (pkey);
4458 mono_metadata_encode_value (len, b, &b);
4459 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4460 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4462 assembly->public_key = g_malloc (len);
4463 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4464 assembly->public_key_len = len;
4466 /* Special case: check for ECMA key (16 bytes) */
4467 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4468 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4469 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4470 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4471 /* minimum key size (in 2.0) is 384 bits */
4472 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4474 /* FIXME - verifier */
4475 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4476 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4478 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4484 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4486 MonoDynamicTable *table;
4487 MonoDynamicImage *assembly;
4488 MonoReflectionAssemblyBuilder *assemblyb;
4492 guint32 module_index;
4494 assemblyb = moduleb->assemblyb;
4495 assembly = moduleb->dynamic_image;
4496 domain = mono_object_domain (assemblyb);
4498 /* Emit ASSEMBLY table */
4499 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4500 alloc_table (table, 1);
4501 values = table->values + MONO_ASSEMBLY_SIZE;
4502 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4503 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4504 if (assemblyb->culture) {
4505 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4507 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4509 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4510 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4511 set_version_from_string (assemblyb->version, values);
4513 /* Emit FILE + EXPORTED_TYPE table */
4515 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4517 MonoReflectionModuleBuilder *file_module =
4518 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4519 if (file_module != moduleb) {
4520 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4522 if (file_module->types) {
4523 for (j = 0; j < file_module->num_types; ++j) {
4524 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4525 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4530 if (assemblyb->loaded_modules) {
4531 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4532 MonoReflectionModule *file_module =
4533 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4534 mono_image_fill_file_table (domain, file_module, assembly);
4536 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4539 if (assemblyb->type_forwarders)
4540 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4542 /* Emit MANIFESTRESOURCE table */
4544 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4546 MonoReflectionModuleBuilder *file_module =
4547 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4548 /* The table for the main module is emitted later */
4549 if (file_module != moduleb) {
4551 if (file_module->resources) {
4552 int len = mono_array_length (file_module->resources);
4553 for (j = 0; j < len; ++j) {
4554 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4555 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4562 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4565 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4566 * for the modulebuilder @moduleb.
4567 * At the end of the process, method and field tokens are fixed up and the
4568 * on-disk compressed metadata representation is created.
4571 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4573 MonoDynamicTable *table;
4574 MonoDynamicImage *assembly;
4575 MonoReflectionAssemblyBuilder *assemblyb;
4581 assemblyb = moduleb->assemblyb;
4582 assembly = moduleb->dynamic_image;
4583 domain = mono_object_domain (assemblyb);
4585 if (assembly->text_rva)
4588 assembly->text_rva = START_TEXT_RVA;
4590 if (moduleb->is_main) {
4591 mono_image_emit_manifest (moduleb);
4594 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4595 table->rows = 1; /* .<Module> */
4597 alloc_table (table, table->rows);
4599 * Set the first entry.
4601 values = table->values + table->columns;
4602 values [MONO_TYPEDEF_FLAGS] = 0;
4603 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4604 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4605 values [MONO_TYPEDEF_EXTENDS] = 0;
4606 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4607 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4610 * handle global methods
4611 * FIXME: test what to do when global methods are defined in multiple modules.
4613 if (moduleb->global_methods) {
4614 table = &assembly->tables [MONO_TABLE_METHOD];
4615 table->rows += mono_array_length (moduleb->global_methods);
4616 alloc_table (table, table->rows);
4617 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4618 mono_image_get_method_info (
4619 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4621 if (moduleb->global_fields) {
4622 table = &assembly->tables [MONO_TABLE_FIELD];
4623 table->rows += mono_array_length (moduleb->global_fields);
4624 alloc_table (table, table->rows);
4625 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4626 mono_image_get_field_info (
4627 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4630 table = &assembly->tables [MONO_TABLE_MODULE];
4631 alloc_table (table, 1);
4632 mono_image_fill_module_table (domain, moduleb, assembly);
4634 /* Collect all types into a list sorted by their table_idx */
4635 mono_ptr_array_init (types, moduleb->num_types);
4638 for (i = 0; i < moduleb->num_types; ++i) {
4639 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4640 collect_types (&types, type);
4643 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4644 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4645 table->rows += mono_ptr_array_size (types);
4646 alloc_table (table, table->rows);
4649 * Emit type names + namespaces at one place inside the string heap,
4650 * so load_class_names () needs to touch fewer pages.
4652 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4653 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4654 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4656 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4657 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4658 string_heap_insert_mstring (&assembly->sheap, tb->name);
4661 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4662 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4663 mono_image_get_type_info (domain, type, assembly);
4667 * table->rows is already set above and in mono_image_fill_module_table.
4669 /* add all the custom attributes at the end, once all the indexes are stable */
4670 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4672 /* CAS assembly permissions */
4673 if (assemblyb->permissions_minimum)
4674 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4675 if (assemblyb->permissions_optional)
4676 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4677 if (assemblyb->permissions_refused)
4678 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4680 module_add_cattrs (assembly, moduleb);
4683 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4685 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4686 * the final tokens and don't need another fixup pass. */
4688 if (moduleb->global_methods) {
4689 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4690 MonoReflectionMethodBuilder *mb = mono_array_get (
4691 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4692 mono_image_add_methodimpl (assembly, mb);
4696 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4697 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4698 if (type->methods) {
4699 for (j = 0; j < type->num_methods; ++j) {
4700 MonoReflectionMethodBuilder *mb = mono_array_get (
4701 type->methods, MonoReflectionMethodBuilder*, j);
4703 mono_image_add_methodimpl (assembly, mb);
4708 mono_ptr_array_destroy (types);
4710 fixup_cattrs (assembly);
4713 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4716 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4718 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4721 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4725 guint32 import_lookup_table;
4729 guint32 import_address_table_rva;
4737 #ifndef DISABLE_REFLECTION_EMIT
4740 * mono_image_insert_string:
4741 * @module: module builder object
4744 * Insert @str into the user string stream of @module.
4747 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4749 MonoDynamicImage *assembly;
4754 MONO_ARCH_SAVE_REGS;
4756 if (!module->dynamic_image)
4757 mono_image_module_basic_init (module);
4759 assembly = module->dynamic_image;
4761 if (assembly->save) {
4762 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4763 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4764 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4766 char *swapped = g_malloc (2 * mono_string_length (str));
4767 const char *p = (const char*)mono_string_chars (str);
4769 swap_with_size (swapped, p, 2, mono_string_length (str));
4770 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4774 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4776 mono_image_add_stream_data (&assembly->us, "", 1);
4778 idx = assembly->us.index ++;
4781 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4783 return MONO_TOKEN_STRING | idx;
4787 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4791 MonoMethodSignature *sig;
4793 klass = obj->vtable->klass;
4794 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4795 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4796 MonoMethodSignature *old;
4797 guint32 sig_token, parent;
4800 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4802 nargs = mono_array_length (opt_param_types);
4803 old = mono_method_signature (method);
4804 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4806 sig->hasthis = old->hasthis;
4807 sig->explicit_this = old->explicit_this;
4808 sig->call_convention = old->call_convention;
4809 sig->generic_param_count = old->generic_param_count;
4810 sig->param_count = old->param_count + nargs;
4811 sig->sentinelpos = old->param_count;
4812 sig->ret = old->ret;
4814 for (i = 0; i < old->param_count; i++)
4815 sig->params [i] = old->params [i];
4817 for (i = 0; i < nargs; i++) {
4818 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4819 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4822 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4823 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4824 parent >>= MONO_TYPEDEFORREF_BITS;
4826 parent <<= MONO_MEMBERREF_PARENT_BITS;
4827 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4829 sig_token = method_encode_signature (assembly, sig);
4830 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4831 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4832 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4833 ReflectionMethodBuilder rmb;
4834 guint32 parent, sig_token;
4835 int nopt_args, nparams, ngparams, i;
4838 reflection_methodbuilder_from_method_builder (&rmb, mb);
4839 rmb.opt_types = opt_param_types;
4840 nopt_args = mono_array_length (opt_param_types);
4842 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4843 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4844 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4846 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4847 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4848 sig->call_convention = rmb.call_conv;
4849 sig->generic_param_count = ngparams;
4850 sig->param_count = nparams + nopt_args;
4851 sig->sentinelpos = nparams;
4852 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4854 for (i = 0; i < nparams; i++) {
4855 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4856 sig->params [i] = mono_reflection_type_get_handle (rt);
4859 for (i = 0; i < nopt_args; i++) {
4860 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4861 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4864 sig_token = method_builder_encode_signature (assembly, &rmb);
4866 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4867 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4869 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4870 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4872 name = mono_string_to_utf8 (rmb.name);
4873 token = mono_image_get_varargs_method_token (
4874 assembly, parent, name, sig_token);
4877 g_error ("requested method token for %s\n", klass->name);
4880 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4881 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4886 * mono_image_create_token:
4887 * @assembly: a dynamic assembly
4889 * @register_token: Whenever to register the token in the assembly->tokens hash.
4891 * Get a token to insert in the IL code stream for the given MemberInfo.
4892 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4893 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4897 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4898 gboolean create_open_instance, gboolean register_token)
4903 klass = obj->vtable->klass;
4905 /* Check for user defined reflection objects */
4906 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4907 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4908 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4910 if (strcmp (klass->name, "MethodBuilder") == 0) {
4911 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4912 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4914 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4915 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4917 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4918 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4919 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4920 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4921 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4923 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4924 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4926 token = mono_image_get_ctorbuilder_token (assembly, mb);
4927 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4928 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4929 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4930 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4931 if (tb->generic_params) {
4932 token = mono_image_get_generic_field_token (assembly, fb);
4934 if (tb->module->dynamic_image == assembly) {
4935 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4937 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4940 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4941 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4942 if (create_open_instance && tb->generic_params) {
4944 init_type_builder_generics (obj);
4945 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4946 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4947 token = mono_metadata_token_from_dor (token);
4948 } else if (tb->module->dynamic_image == assembly) {
4949 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4952 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4953 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4955 } else if (strcmp (klass->name, "MonoType") == 0) {
4956 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4957 MonoClass *mc = mono_class_from_mono_type (type);
4958 token = mono_metadata_token_from_dor (
4959 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4960 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4961 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4962 token = mono_metadata_token_from_dor (
4963 mono_image_typedef_or_ref (assembly, type));
4964 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4965 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966 token = mono_metadata_token_from_dor (
4967 mono_image_typedef_or_ref (assembly, type));
4968 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4969 strcmp (klass->name, "MonoMethod") == 0 ||
4970 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4971 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4972 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4973 if (m->method->is_inflated) {
4974 if (create_open_instance)
4975 token = mono_image_get_methodspec_token (assembly, m->method);
4977 token = mono_image_get_inflated_method_token (assembly, m->method);
4978 } else if ((m->method->klass->image == &assembly->image) &&
4979 !m->method->klass->generic_class) {
4980 static guint32 method_table_idx = 0xffffff;
4981 if (m->method->klass->wastypebuilder) {
4982 /* we use the same token as the one that was assigned
4983 * to the Methodbuilder.
4984 * FIXME: do the equivalent for Fields.
4986 token = m->method->token;
4989 * Each token should have a unique index, but the indexes are
4990 * assigned by managed code, so we don't know about them. An
4991 * easy solution is to count backwards...
4993 method_table_idx --;
4994 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4997 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4999 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5000 } else if (strcmp (klass->name, "MonoField") == 0) {
5001 MonoReflectionField *f = (MonoReflectionField *)obj;
5002 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5003 static guint32 field_table_idx = 0xffffff;
5005 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5007 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5009 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5010 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5011 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5012 token = mono_image_get_array_token (assembly, m);
5013 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5014 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5015 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5016 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5017 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5018 token = mono_metadata_token_from_dor (
5019 mono_image_typedef_or_ref (assembly, type));
5020 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5021 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5022 token = mono_image_get_field_on_inst_token (assembly, f);
5023 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5024 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5025 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5026 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5027 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5028 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5029 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5030 MonoReflectionType *type = (MonoReflectionType *)obj;
5031 token = mono_metadata_token_from_dor (
5032 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5034 g_error ("requested token for %s\n", klass->name);
5038 mono_image_register_token (assembly, token, obj);
5044 * mono_image_register_token:
5046 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5047 * the Module.ResolveXXXToken () methods to work.
5050 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5052 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5054 /* There could be multiple MethodInfo objects with the same token */
5055 //g_assert (prev == obj);
5057 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5061 static MonoDynamicImage*
5062 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5064 static const guchar entrycode [16] = {0xff, 0x25, 0};
5065 MonoDynamicImage *image;
5068 const char *version;
5070 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5071 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5073 version = mono_get_runtime_info ()->runtime_version;
5076 /* The MonoGHashTable's need GC tracking */
5077 image = GC_MALLOC (sizeof (MonoDynamicImage));
5079 image = g_new0 (MonoDynamicImage, 1);
5082 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5084 /*g_print ("created image %p\n", image);*/
5085 /* keep in sync with image.c */
5086 image->image.name = assembly_name;
5087 image->image.assembly_name = image->image.name; /* they may be different */
5088 image->image.module_name = module_name;
5089 image->image.version = g_strdup (version);
5090 image->image.md_version_major = 1;
5091 image->image.md_version_minor = 1;
5092 image->image.dynamic = TRUE;
5094 image->image.references = g_new0 (MonoAssembly*, 1);
5095 image->image.references [0] = NULL;
5097 mono_image_init (&image->image);
5099 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5100 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5101 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5102 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5103 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5104 image->handleref = g_hash_table_new (NULL, NULL);
5105 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5106 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5107 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5108 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5109 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5110 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5111 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5112 image->gen_params = g_ptr_array_new ();
5113 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5115 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5116 string_heap_init (&image->sheap);
5117 mono_image_add_stream_data (&image->us, "", 1);
5118 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5119 /* import tables... */
5120 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5121 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5122 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5123 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5124 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5125 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5126 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5127 stream_data_align (&image->code);
5129 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5131 for (i=0; i < MONO_TABLE_NUM; ++i) {
5132 image->tables [i].next_idx = 1;
5133 image->tables [i].columns = table_sizes [i];
5136 image->image.assembly = (MonoAssembly*)assembly;
5137 image->run = assembly->run;
5138 image->save = assembly->save;
5139 image->pe_kind = 0x1; /* ILOnly */
5140 image->machine = 0x14c; /* I386 */
5142 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5149 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5155 release_hashtable (MonoGHashTable **hash)
5158 mono_g_hash_table_destroy (*hash);
5164 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5166 release_hashtable (&image->token_fixups);
5167 release_hashtable (&image->handleref_managed);
5168 release_hashtable (&image->tokens);
5169 release_hashtable (&image->remapped_tokens);
5170 release_hashtable (&image->generic_def_objects);
5171 release_hashtable (&image->methodspec);
5175 mono_dynamic_image_free (MonoDynamicImage *image)
5177 MonoDynamicImage *di = image;
5182 mono_g_hash_table_destroy (di->methodspec);
5184 g_hash_table_destroy (di->typespec);
5186 g_hash_table_destroy (di->typeref);
5188 g_hash_table_destroy (di->handleref);
5189 if (di->handleref_managed)
5190 mono_g_hash_table_destroy (di->handleref_managed);
5192 mono_g_hash_table_destroy (di->tokens);
5193 if (di->remapped_tokens)
5194 mono_g_hash_table_destroy (di->remapped_tokens);
5195 if (di->generic_def_objects)
5196 mono_g_hash_table_destroy (di->generic_def_objects);
5197 if (di->blob_cache) {
5198 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5199 g_hash_table_destroy (di->blob_cache);
5201 if (di->standalonesig_cache)
5202 g_hash_table_destroy (di->standalonesig_cache);
5203 for (list = di->array_methods; list; list = list->next) {
5204 ArrayMethod *am = (ArrayMethod *)list->data;
5209 g_list_free (di->array_methods);
5210 if (di->gen_params) {
5211 for (i = 0; i < di->gen_params->len; i++) {
5212 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5213 mono_gc_deregister_root ((char*) &entry->gparam);
5216 g_ptr_array_free (di->gen_params, TRUE);
5218 if (di->token_fixups)
5219 mono_g_hash_table_destroy (di->token_fixups);
5220 if (di->method_to_table_idx)
5221 g_hash_table_destroy (di->method_to_table_idx);
5222 if (di->field_to_table_idx)
5223 g_hash_table_destroy (di->field_to_table_idx);
5224 if (di->method_aux_hash)
5225 g_hash_table_destroy (di->method_aux_hash);
5226 if (di->vararg_aux_hash)
5227 g_hash_table_destroy (di->vararg_aux_hash);
5228 g_free (di->strong_name);
5229 g_free (di->win32_res);
5231 g_free (di->public_key);
5233 /*g_print ("string heap destroy for image %p\n", di);*/
5234 mono_dynamic_stream_reset (&di->sheap);
5235 mono_dynamic_stream_reset (&di->code);
5236 mono_dynamic_stream_reset (&di->resources);
5237 mono_dynamic_stream_reset (&di->us);
5238 mono_dynamic_stream_reset (&di->blob);
5239 mono_dynamic_stream_reset (&di->tstream);
5240 mono_dynamic_stream_reset (&di->guid);
5241 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5242 g_free (di->tables [i].values);
5246 #ifndef DISABLE_REFLECTION_EMIT
5249 * mono_image_basic_init:
5250 * @assembly: an assembly builder object
5252 * Create the MonoImage that represents the assembly builder and setup some
5253 * of the helper hash table and the basic metadata streams.
5256 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5258 MonoDynamicAssembly *assembly;
5259 MonoDynamicImage *image;
5260 MonoDomain *domain = mono_object_domain (assemblyb);
5262 MONO_ARCH_SAVE_REGS;
5264 if (assemblyb->dynamic_assembly)
5268 /* assembly->assembly.image might be GC allocated */
5269 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5271 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5274 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5276 assembly->assembly.ref_count = 1;
5277 assembly->assembly.dynamic = TRUE;
5278 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5279 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5280 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5281 if (assemblyb->culture)
5282 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5284 assembly->assembly.aname.culture = g_strdup ("");
5286 if (assemblyb->version) {
5287 char *vstr = mono_string_to_utf8 (assemblyb->version);
5288 char **version = g_strsplit (vstr, ".", 4);
5289 char **parts = version;
5290 assembly->assembly.aname.major = atoi (*parts++);
5291 assembly->assembly.aname.minor = atoi (*parts++);
5292 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5293 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5295 g_strfreev (version);
5298 assembly->assembly.aname.major = 0;
5299 assembly->assembly.aname.minor = 0;
5300 assembly->assembly.aname.build = 0;
5301 assembly->assembly.aname.revision = 0;
5304 assembly->run = assemblyb->access != 2;
5305 assembly->save = assemblyb->access != 1;
5306 assembly->domain = domain;
5308 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5309 image->initial_image = TRUE;
5310 assembly->assembly.aname.name = image->image.name;
5311 assembly->assembly.image = &image->image;
5312 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5313 /* -1 to correct for the trailing NULL byte */
5314 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5315 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5317 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5320 mono_domain_assemblies_lock (domain);
5321 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5322 mono_domain_assemblies_unlock (domain);
5324 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5326 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5328 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5331 #endif /* !DISABLE_REFLECTION_EMIT */
5333 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5336 calc_section_size (MonoDynamicImage *assembly)
5340 /* alignment constraints */
5341 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5342 g_assert ((assembly->code.index % 4) == 0);
5343 assembly->meta_size += 3;
5344 assembly->meta_size &= ~3;
5345 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5346 g_assert ((assembly->resources.index % 4) == 0);
5348 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5349 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5352 if (assembly->win32_res) {
5353 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5355 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5356 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5360 assembly->sections [MONO_SECTION_RELOC].size = 12;
5361 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5371 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5375 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5377 ResTreeNode *t1 = (ResTreeNode*)a;
5378 ResTreeNode *t2 = (ResTreeNode*)b;
5380 return t1->id - t2->id;
5384 * resource_tree_create:
5386 * Organize the resources into a resource tree.
5388 static ResTreeNode *
5389 resource_tree_create (MonoArray *win32_resources)
5391 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5395 tree = g_new0 (ResTreeNode, 1);
5397 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5398 MonoReflectionWin32Resource *win32_res =
5399 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5403 /* FIXME: BUG: this stores managed references in unmanaged memory */
5404 lang_node = g_new0 (ResTreeNode, 1);
5405 lang_node->id = win32_res->lang_id;
5406 lang_node->win32_res = win32_res;
5408 /* Create type node if neccesary */
5410 for (l = tree->children; l; l = l->next)
5411 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5412 type_node = (ResTreeNode*)l->data;
5417 type_node = g_new0 (ResTreeNode, 1);
5418 type_node->id = win32_res->res_type;
5421 * The resource types have to be sorted otherwise
5422 * Windows Explorer can't display the version information.
5424 tree->children = g_slist_insert_sorted (tree->children,
5425 type_node, resource_tree_compare_by_id);
5428 /* Create res node if neccesary */
5430 for (l = type_node->children; l; l = l->next)
5431 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5432 res_node = (ResTreeNode*)l->data;
5437 res_node = g_new0 (ResTreeNode, 1);
5438 res_node->id = win32_res->res_id;
5439 type_node->children = g_slist_append (type_node->children, res_node);
5442 res_node->children = g_slist_append (res_node->children, lang_node);
5449 * resource_tree_encode:
5451 * Encode the resource tree into the format used in the PE file.
5454 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5457 MonoPEResourceDir dir;
5458 MonoPEResourceDirEntry dir_entry;
5459 MonoPEResourceDataEntry data_entry;
5461 guint32 res_id_entries;
5464 * For the format of the resource directory, see the article
5465 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5469 memset (&dir, 0, sizeof (dir));
5470 memset (&dir_entry, 0, sizeof (dir_entry));
5471 memset (&data_entry, 0, sizeof (data_entry));
5473 g_assert (sizeof (dir) == 16);
5474 g_assert (sizeof (dir_entry) == 8);
5475 g_assert (sizeof (data_entry) == 16);
5477 node->offset = p - begin;
5479 /* IMAGE_RESOURCE_DIRECTORY */
5480 res_id_entries = g_slist_length (node->children);
5481 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5483 memcpy (p, &dir, sizeof (dir));
5486 /* Reserve space for entries */
5488 p += sizeof (dir_entry) * res_id_entries;
5490 /* Write children */
5491 for (l = node->children; l; l = l->next) {
5492 ResTreeNode *child = (ResTreeNode*)l->data;
5494 if (child->win32_res) {
5497 child->offset = p - begin;
5499 /* IMAGE_RESOURCE_DATA_ENTRY */
5500 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5501 size = mono_array_length (child->win32_res->res_data);
5502 data_entry.rde_size = GUINT32_TO_LE (size);
5504 memcpy (p, &data_entry, sizeof (data_entry));
5505 p += sizeof (data_entry);
5507 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5510 resource_tree_encode (child, begin, p, &p);
5514 /* IMAGE_RESOURCE_ENTRY */
5515 for (l = node->children; l; l = l->next) {
5516 ResTreeNode *child = (ResTreeNode*)l->data;
5518 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5519 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5521 memcpy (entries, &dir_entry, sizeof (dir_entry));
5522 entries += sizeof (dir_entry);
5529 resource_tree_free (ResTreeNode * node)
5532 for (list = node->children; list; list = list->next)
5533 resource_tree_free ((ResTreeNode*)list->data);
5534 g_slist_free(node->children);
5539 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5544 MonoReflectionWin32Resource *win32_res;
5547 if (!assemblyb->win32_resources)
5551 * Resources are stored in a three level tree inside the PE file.
5552 * - level one contains a node for each type of resource
5553 * - level two contains a node for each resource
5554 * - level three contains a node for each instance of a resource for a
5555 * specific language.
5558 tree = resource_tree_create (assemblyb->win32_resources);
5560 /* Estimate the size of the encoded tree */
5562 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5563 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5564 size += mono_array_length (win32_res->res_data);
5566 /* Directory structure */
5567 size += mono_array_length (assemblyb->win32_resources) * 256;
5568 p = buf = g_malloc (size);
5570 resource_tree_encode (tree, p, p, &p);
5572 g_assert (p - buf <= size);
5574 assembly->win32_res = g_malloc (p - buf);
5575 assembly->win32_res_size = p - buf;
5576 memcpy (assembly->win32_res, buf, p - buf);
5579 resource_tree_free (tree);
5583 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5585 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5588 p += sizeof (MonoPEResourceDir);
5589 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5590 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5591 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5592 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5593 fixup_resource_directory (res_section, child, rva);
5595 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5596 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5599 p += sizeof (MonoPEResourceDirEntry);
5604 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5607 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5608 g_error ("WriteFile returned %d\n", GetLastError ());
5612 * mono_image_create_pefile:
5613 * @mb: a module builder object
5615 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5616 * assembly->pefile where it can be easily retrieved later in chunks.
5619 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5621 MonoMSDOSHeader *msdos;
5622 MonoDotNetHeader *header;
5623 MonoSectionTable *section;
5624 MonoCLIHeader *cli_header;
5625 guint32 size, image_size, virtual_base, text_offset;
5626 guint32 header_start, section_start, file_offset, virtual_offset;
5627 MonoDynamicImage *assembly;
5628 MonoReflectionAssemblyBuilder *assemblyb;
5629 MonoDynamicStream pefile_stream = {0};
5630 MonoDynamicStream *pefile = &pefile_stream;
5632 guint32 *rva, value;
5634 static const unsigned char msheader[] = {
5635 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5636 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5639 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5640 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5641 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5642 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5645 assemblyb = mb->assemblyb;
5647 mono_image_basic_init (assemblyb);
5648 assembly = mb->dynamic_image;
5650 assembly->pe_kind = assemblyb->pe_kind;
5651 assembly->machine = assemblyb->machine;
5652 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5653 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5655 mono_image_build_metadata (mb);
5657 if (mb->is_main && assemblyb->resources) {
5658 int len = mono_array_length (assemblyb->resources);
5659 for (i = 0; i < len; ++i)
5660 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5663 if (mb->resources) {
5664 int len = mono_array_length (mb->resources);
5665 for (i = 0; i < len; ++i)
5666 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5669 build_compressed_metadata (assembly);
5672 assembly_add_win32_resources (assembly, assemblyb);
5674 nsections = calc_section_size (assembly);
5676 /* The DOS header and stub */
5677 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5678 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5680 /* the dotnet header */
5681 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5683 /* the section tables */
5684 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5686 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5687 virtual_offset = VIRT_ALIGN;
5690 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5691 if (!assembly->sections [i].size)
5694 file_offset += FILE_ALIGN - 1;
5695 file_offset &= ~(FILE_ALIGN - 1);
5696 virtual_offset += VIRT_ALIGN - 1;
5697 virtual_offset &= ~(VIRT_ALIGN - 1);
5699 assembly->sections [i].offset = file_offset;
5700 assembly->sections [i].rva = virtual_offset;
5702 file_offset += assembly->sections [i].size;
5703 virtual_offset += assembly->sections [i].size;
5704 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5707 file_offset += FILE_ALIGN - 1;
5708 file_offset &= ~(FILE_ALIGN - 1);
5710 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5712 /* back-patch info */
5713 msdos = (MonoMSDOSHeader*)pefile->data;
5714 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5716 header = (MonoDotNetHeader*)(pefile->data + header_start);
5717 header->pesig [0] = 'P';
5718 header->pesig [1] = 'E';
5720 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5721 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5722 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5723 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5724 if (assemblyb->pekind == 1) {
5726 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5729 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5732 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5734 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5735 header->pe.pe_major = 6;
5736 header->pe.pe_minor = 0;
5737 size = assembly->sections [MONO_SECTION_TEXT].size;
5738 size += FILE_ALIGN - 1;
5739 size &= ~(FILE_ALIGN - 1);
5740 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5741 size = assembly->sections [MONO_SECTION_RSRC].size;
5742 size += FILE_ALIGN - 1;
5743 size &= ~(FILE_ALIGN - 1);
5744 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5745 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5746 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5747 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5748 /* pe_rva_entry_point always at the beginning of the text section */
5749 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5751 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5752 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5753 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5754 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5755 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5756 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5757 size = section_start;
5758 size += FILE_ALIGN - 1;
5759 size &= ~(FILE_ALIGN - 1);
5760 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5762 size += VIRT_ALIGN - 1;
5763 size &= ~(VIRT_ALIGN - 1);
5764 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5767 // Translate the PEFileKind value to the value expected by the Windows loader
5773 // PEFileKinds.Dll == 1
5774 // PEFileKinds.ConsoleApplication == 2
5775 // PEFileKinds.WindowApplication == 3
5778 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5779 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5781 if (assemblyb->pekind == 3)
5786 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5788 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5789 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5790 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5791 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5792 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5793 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5795 /* fill data directory entries */
5797 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5798 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5800 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5801 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5803 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5804 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5805 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5806 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5807 /* patch entrypoint name */
5808 if (assemblyb->pekind == 1)
5809 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5811 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5812 /* patch imported function RVA name */
5813 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5814 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5816 /* the import table */
5817 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5818 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5819 /* patch imported dll RVA name and other entries in the dir */
5820 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5821 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5822 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5823 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5824 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5825 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5827 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5828 value = (assembly->text_rva + assembly->imp_names_offset);
5829 *p++ = (value) & 0xff;
5830 *p++ = (value >> 8) & (0xff);
5831 *p++ = (value >> 16) & (0xff);
5832 *p++ = (value >> 24) & (0xff);
5834 /* the CLI header info */
5835 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5836 cli_header->ch_size = GUINT32_FROM_LE (72);
5837 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5838 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5839 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5840 if (assemblyb->entry_point) {
5841 guint32 table_idx = 0;
5842 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5843 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5844 table_idx = methodb->table_idx;
5846 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5848 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5850 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5852 /* The embedded managed resources */
5853 text_offset = assembly->text_rva + assembly->code.index;
5854 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5855 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5856 text_offset += assembly->resources.index;
5857 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5858 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5859 text_offset += assembly->meta_size;
5860 if (assembly->strong_name_size) {
5861 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5862 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5863 text_offset += assembly->strong_name_size;
5866 /* write the section tables and section content */
5867 section = (MonoSectionTable*)(pefile->data + section_start);
5868 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5869 static const char section_names [][7] = {
5870 ".text", ".rsrc", ".reloc"
5872 if (!assembly->sections [i].size)
5874 strcpy (section->st_name, section_names [i]);
5875 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5876 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5877 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5878 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5879 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5880 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5881 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5885 checked_write_file (file, pefile->data, pefile->index);
5887 mono_dynamic_stream_reset (pefile);
5889 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5890 if (!assembly->sections [i].size)
5893 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5894 g_error ("SetFilePointer returned %d\n", GetLastError ());
5897 case MONO_SECTION_TEXT:
5898 /* patch entry point */
5899 p = (guchar*)(assembly->code.data + 2);
5900 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5901 *p++ = (value) & 0xff;
5902 *p++ = (value >> 8) & 0xff;
5903 *p++ = (value >> 16) & 0xff;
5904 *p++ = (value >> 24) & 0xff;
5906 checked_write_file (file, assembly->code.data, assembly->code.index);
5907 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5908 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5909 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5912 g_free (assembly->image.raw_metadata);
5914 case MONO_SECTION_RELOC: {
5918 guint16 type_and_offset;
5922 g_assert (sizeof (reloc) == 12);
5924 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5925 reloc.block_size = GUINT32_FROM_LE (12);
5928 * the entrypoint is always at the start of the text section
5929 * 3 is IMAGE_REL_BASED_HIGHLOW
5930 * 2 is patch_size_rva - text_rva
5932 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5935 checked_write_file (file, &reloc, sizeof (reloc));
5939 case MONO_SECTION_RSRC:
5940 if (assembly->win32_res) {
5942 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5943 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5944 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5948 g_assert_not_reached ();
5952 /* check that the file is properly padded */
5953 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5954 g_error ("SetFilePointer returned %d\n", GetLastError ());
5955 if (! SetEndOfFile (file))
5956 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5958 mono_dynamic_stream_reset (&assembly->code);
5959 mono_dynamic_stream_reset (&assembly->us);
5960 mono_dynamic_stream_reset (&assembly->blob);
5961 mono_dynamic_stream_reset (&assembly->guid);
5962 mono_dynamic_stream_reset (&assembly->sheap);
5964 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5965 g_hash_table_destroy (assembly->blob_cache);
5966 assembly->blob_cache = NULL;
5969 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5972 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5974 g_assert_not_reached ();
5977 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5979 #ifndef DISABLE_REFLECTION_EMIT
5981 MonoReflectionModule *
5982 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5986 MonoImageOpenStatus status;
5987 MonoDynamicAssembly *assembly;
5988 guint32 module_count;
5989 MonoImage **new_modules;
5990 gboolean *new_modules_loaded;
5992 name = mono_string_to_utf8 (fileName);
5994 image = mono_image_open (name, &status);
5997 if (status == MONO_IMAGE_ERROR_ERRNO)
5998 exc = mono_get_exception_file_not_found (fileName);
6000 exc = mono_get_exception_bad_image_format (name);
6002 mono_raise_exception (exc);
6007 assembly = ab->dynamic_assembly;
6008 image->assembly = (MonoAssembly*)assembly;
6010 module_count = image->assembly->image->module_count;
6011 new_modules = g_new0 (MonoImage *, module_count + 1);
6012 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6014 if (image->assembly->image->modules)
6015 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6016 if (image->assembly->image->modules_loaded)
6017 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6018 new_modules [module_count] = image;
6019 new_modules_loaded [module_count] = TRUE;
6020 mono_image_addref (image);
6022 g_free (image->assembly->image->modules);
6023 image->assembly->image->modules = new_modules;
6024 image->assembly->image->modules_loaded = new_modules_loaded;
6025 image->assembly->image->module_count ++;
6027 mono_assembly_load_references (image, &status);
6029 mono_image_close (image);
6030 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6033 return mono_module_get_object (mono_domain_get (), image);
6036 #endif /* DISABLE_REFLECTION_EMIT */
6039 * We need to return always the same object for MethodInfo, FieldInfo etc..
6040 * but we need to consider the reflected type.
6041 * type uses a different hash, since it uses custom hash/equal functions.
6046 MonoClass *refclass;
6050 reflected_equal (gconstpointer a, gconstpointer b) {
6051 const ReflectedEntry *ea = a;
6052 const ReflectedEntry *eb = b;
6054 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6058 reflected_hash (gconstpointer a) {
6059 const ReflectedEntry *ea = a;
6060 return mono_aligned_addr_hash (ea->item);
6063 #define CHECK_OBJECT(t,p,k) \
6069 mono_domain_lock (domain); \
6070 if (!domain->refobject_hash) \
6071 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6072 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6073 mono_domain_unlock (domain); \
6076 mono_domain_unlock (domain); \
6079 #ifdef HAVE_BOEHM_GC
6080 /* ReflectedEntry doesn't need to be GC tracked */
6081 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6082 #define FREE_REFENTRY(entry) g_free ((entry))
6083 #define REFENTRY_REQUIRES_CLEANUP
6085 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6087 #define FREE_REFENTRY(entry)
6090 #define CACHE_OBJECT(t,p,o,k) \
6093 ReflectedEntry pe; \
6095 pe.refclass = (k); \
6096 mono_domain_lock (domain); \
6097 if (!domain->refobject_hash) \
6098 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6099 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6101 ReflectedEntry *e = ALLOC_REFENTRY; \
6103 e->refclass = (k); \
6104 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6107 mono_domain_unlock (domain); \
6112 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6114 mono_domain_lock (domain);
6115 if (domain->refobject_hash) {
6117 gpointer orig_pe, orig_value;
6120 pe.refclass = klass;
6121 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6122 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6123 FREE_REFENTRY (orig_pe);
6126 mono_domain_unlock (domain);
6129 #ifdef REFENTRY_REQUIRES_CLEANUP
6131 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6133 FREE_REFENTRY (key);
6138 mono_reflection_cleanup_domain (MonoDomain *domain)
6140 if (domain->refobject_hash) {
6141 /*let's avoid scanning the whole hashtable if not needed*/
6142 #ifdef REFENTRY_REQUIRES_CLEANUP
6143 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6145 mono_g_hash_table_destroy (domain->refobject_hash);
6146 domain->refobject_hash = NULL;
6150 #ifndef DISABLE_REFLECTION_EMIT
6152 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6154 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6158 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6160 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6164 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6166 MonoDynamicImage *image = moduleb->dynamic_image;
6167 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6171 MonoImage **new_modules;
6173 char *name, *fqname;
6175 * FIXME: we already created an image in mono_image_basic_init (), but
6176 * we don't know which module it belongs to, since that is only
6177 * determined at assembly save time.
6179 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6180 name = mono_string_to_utf8 (ab->name);
6181 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6182 if (!mono_error_ok (&error)) {
6184 mono_error_raise_exception (&error);
6186 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6188 moduleb->module.image = &image->image;
6189 moduleb->dynamic_image = image;
6190 register_module (mono_object_domain (moduleb), moduleb, image);
6192 /* register the module with the assembly */
6193 ass = ab->dynamic_assembly->assembly.image;
6194 module_count = ass->module_count;
6195 new_modules = g_new0 (MonoImage *, module_count + 1);
6198 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6199 new_modules [module_count] = &image->image;
6200 mono_image_addref (&image->image);
6202 g_free (ass->modules);
6203 ass->modules = new_modules;
6204 ass->module_count ++;
6209 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6211 MonoDynamicImage *image = moduleb->dynamic_image;
6213 g_assert (type->type);
6214 image->wrappers_type = mono_class_from_mono_type (type->type);
6220 * mono_assembly_get_object:
6221 * @domain: an app domain
6222 * @assembly: an assembly
6224 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6226 MonoReflectionAssembly*
6227 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6229 static MonoClass *assembly_type;
6230 MonoReflectionAssembly *res;
6232 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6233 if (!assembly_type) {
6234 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6236 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6238 assembly_type = class;
6240 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6241 res->assembly = assembly;
6243 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6248 MonoReflectionModule*
6249 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6251 static MonoClass *module_type;
6252 MonoReflectionModule *res;
6255 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6257 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6259 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6261 module_type = class;
6263 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6266 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6268 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6269 basename = g_path_get_basename (image->name);
6270 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6271 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6275 if (image->assembly->image == image) {
6276 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6280 if (image->assembly->image->modules) {
6281 for (i = 0; i < image->assembly->image->module_count; i++) {
6282 if (image->assembly->image->modules [i] == image)
6283 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6285 g_assert (res->token);
6289 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6292 MonoReflectionModule*
6293 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6295 static MonoClass *module_type;
6296 MonoReflectionModule *res;
6297 MonoTableInfo *table;
6298 guint32 cols [MONO_FILE_SIZE];
6300 guint32 i, name_idx;
6304 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6306 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6308 module_type = class;
6310 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6312 table = &image->tables [MONO_TABLE_FILE];
6313 g_assert (table_index < table->rows);
6314 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6317 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6318 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6320 /* Check whenever the row has a corresponding row in the moduleref table */
6321 table = &image->tables [MONO_TABLE_MODULEREF];
6322 for (i = 0; i < table->rows; ++i) {
6323 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6324 val = mono_metadata_string_heap (image, name_idx);
6325 if (strcmp (val, name) == 0)
6326 res->image = image->modules [i];
6329 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6330 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6331 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6332 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6333 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6339 verify_safe_for_managed_space (MonoType *type)
6341 switch (type->type) {
6343 case MONO_TYPE_ARRAY:
6344 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6346 return verify_safe_for_managed_space (type->data.type);
6347 case MONO_TYPE_SZARRAY:
6348 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6349 case MONO_TYPE_GENERICINST: {
6350 MonoGenericInst *inst = type->data.generic_class->inst;
6354 for (i = 0; i < inst->type_argc; ++i)
6355 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6361 case MONO_TYPE_MVAR:
6368 mono_type_normalize (MonoType *type)
6371 MonoGenericClass *gclass;
6372 MonoGenericInst *ginst;
6374 MonoGenericContainer *gcontainer;
6375 MonoType **argv = NULL;
6376 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6378 if (type->type != MONO_TYPE_GENERICINST)
6381 gclass = type->data.generic_class;
6382 ginst = gclass->context.class_inst;
6383 if (!ginst->is_open)
6386 gtd = gclass->container_class;
6387 gcontainer = gtd->generic_container;
6388 argv = g_newa (MonoType*, ginst->type_argc);
6390 for (i = 0; i < ginst->type_argc; ++i) {
6391 MonoType *t = ginst->type_argv [i], *norm;
6392 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6393 is_denorm_gtd = FALSE;
6394 norm = mono_type_normalize (t);
6397 requires_rebind = TRUE;
6401 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6403 if (requires_rebind) {
6404 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6405 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6411 * mono_type_get_object:
6412 * @domain: an app domain
6415 * Return an System.MonoType object representing the type @type.
6418 mono_type_get_object (MonoDomain *domain, MonoType *type)
6420 MonoType *norm_type;
6421 MonoReflectionType *res;
6422 MonoClass *klass = mono_class_from_mono_type (type);
6424 /*we must avoid using @type as it might have come
6425 * from a mono_metadata_type_dup and the caller
6426 * expects that is can be freed.
6427 * Using the right type from
6429 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6431 /* void is very common */
6432 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6433 return (MonoReflectionType*)domain->typeof_void;
6436 * If the vtable of the given class was already created, we can use
6437 * the MonoType from there and avoid all locking and hash table lookups.
6439 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6440 * that the resulting object is different.
6442 if (type == &klass->byval_arg && !klass->image->dynamic) {
6443 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6444 if (vtable && vtable->type)
6445 return vtable->type;
6448 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6449 mono_domain_lock (domain);
6450 if (!domain->type_hash)
6451 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6452 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6453 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6454 mono_domain_unlock (domain);
6455 mono_loader_unlock ();
6459 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6460 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6461 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6462 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6463 * artifact of how generics are encoded and should be transparent to managed code so we
6464 * need to weed out this diference when retrieving managed System.Type objects.
6466 norm_type = mono_type_normalize (type);
6467 if (norm_type != type) {
6468 res = mono_type_get_object (domain, norm_type);
6469 mono_g_hash_table_insert (domain->type_hash, type, res);
6470 mono_domain_unlock (domain);
6471 mono_loader_unlock ();
6475 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6476 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6479 if (!verify_safe_for_managed_space (type)) {
6480 mono_domain_unlock (domain);
6481 mono_loader_unlock ();
6482 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6485 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6486 gboolean is_type_done = TRUE;
6487 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6488 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6489 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6491 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6492 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6494 if (gparam->owner && gparam->owner->is_method) {
6495 MonoMethod *method = gparam->owner->owner.method;
6496 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6497 is_type_done = FALSE;
6498 } else if (gparam->owner && !gparam->owner->is_method) {
6499 MonoClass *klass = gparam->owner->owner.klass;
6500 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6501 is_type_done = FALSE;
6505 /* g_assert_not_reached (); */
6506 /* should this be considered an error condition? */
6507 if (is_type_done && !type->byref) {
6508 mono_domain_unlock (domain);
6509 mono_loader_unlock ();
6510 return mono_class_get_ref_info (klass);
6513 /* This is stored in vtables/JITted code so it has to be pinned */
6514 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6516 mono_g_hash_table_insert (domain->type_hash, type, res);
6518 if (type->type == MONO_TYPE_VOID)
6519 domain->typeof_void = (MonoObject*)res;
6521 mono_domain_unlock (domain);
6522 mono_loader_unlock ();
6527 * mono_method_get_object:
6528 * @domain: an app domain
6530 * @refclass: the reflected type (can be NULL)
6532 * Return an System.Reflection.MonoMethod object representing the method @method.
6534 MonoReflectionMethod*
6535 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6538 * We use the same C representation for methods and constructors, but the type
6539 * name in C# is different.
6541 static MonoClass *System_Reflection_MonoMethod = NULL;
6542 static MonoClass *System_Reflection_MonoCMethod = NULL;
6543 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6544 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6546 MonoReflectionMethod *ret;
6548 if (method->is_inflated) {
6549 MonoReflectionGenericMethod *gret;
6551 refclass = method->klass;
6552 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6553 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6554 if (!System_Reflection_MonoGenericCMethod)
6555 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6556 klass = System_Reflection_MonoGenericCMethod;
6558 if (!System_Reflection_MonoGenericMethod)
6559 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6560 klass = System_Reflection_MonoGenericMethod;
6562 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6563 gret->method.method = method;
6564 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6565 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6566 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6570 refclass = method->klass;
6572 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6573 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6574 if (!System_Reflection_MonoCMethod)
6575 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6576 klass = System_Reflection_MonoCMethod;
6579 if (!System_Reflection_MonoMethod)
6580 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6581 klass = System_Reflection_MonoMethod;
6583 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6584 ret->method = method;
6585 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6586 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6590 * mono_method_clear_object:
6592 * Clear the cached reflection objects for the dynamic method METHOD.
6595 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6598 g_assert (method->dynamic);
6600 klass = method->klass;
6602 clear_cached_object (domain, method, klass);
6603 klass = klass->parent;
6605 /* Added by mono_param_get_objects () */
6606 clear_cached_object (domain, &(method->signature), NULL);
6607 klass = method->klass;
6609 clear_cached_object (domain, &(method->signature), klass);
6610 klass = klass->parent;
6615 * mono_field_get_object:
6616 * @domain: an app domain
6620 * Return an System.Reflection.MonoField object representing the field @field
6623 MonoReflectionField*
6624 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6626 MonoReflectionField *res;
6627 static MonoClass *monofield_klass;
6629 CHECK_OBJECT (MonoReflectionField *, field, klass);
6630 if (!monofield_klass)
6631 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6632 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6635 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6637 if (is_field_on_inst (field)) {
6638 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6639 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6642 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6643 res->attrs = mono_field_get_flags (field);
6645 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6649 * mono_property_get_object:
6650 * @domain: an app domain
6652 * @property: a property
6654 * Return an System.Reflection.MonoProperty object representing the property @property
6657 MonoReflectionProperty*
6658 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6660 MonoReflectionProperty *res;
6661 static MonoClass *monoproperty_klass;
6663 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6664 if (!monoproperty_klass)
6665 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6666 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6668 res->property = property;
6669 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6673 * mono_event_get_object:
6674 * @domain: an app domain
6678 * Return an System.Reflection.MonoEvent object representing the event @event
6681 MonoReflectionEvent*
6682 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6684 MonoReflectionEvent *res;
6685 MonoReflectionMonoEvent *mono_event;
6686 static MonoClass *monoevent_klass;
6688 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6689 if (!monoevent_klass)
6690 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6691 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6692 mono_event->klass = klass;
6693 mono_event->event = event;
6694 res = (MonoReflectionEvent*)mono_event;
6695 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6699 * mono_get_reflection_missing_object:
6700 * @domain: Domain where the object lives
6702 * Returns the System.Reflection.Missing.Value singleton object
6703 * (of type System.Reflection.Missing).
6705 * Used as the value for ParameterInfo.DefaultValue when Optional
6709 mono_get_reflection_missing_object (MonoDomain *domain)
6712 static MonoClassField *missing_value_field = NULL;
6714 if (!missing_value_field) {
6715 MonoClass *missing_klass;
6716 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6717 mono_class_init (missing_klass);
6718 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6719 g_assert (missing_value_field);
6721 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6727 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6730 *dbnull = mono_get_dbnull_object (domain);
6735 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6737 if (!*reflection_missing)
6738 *reflection_missing = mono_get_reflection_missing_object (domain);
6739 return *reflection_missing;
6743 * mono_param_get_objects:
6744 * @domain: an app domain
6747 * Return an System.Reflection.ParameterInfo array object representing the parameters
6748 * in the method @method.
6751 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6753 static MonoClass *System_Reflection_ParameterInfo;
6754 static MonoClass *System_Reflection_ParameterInfo_array;
6756 MonoArray *res = NULL;
6757 MonoReflectionMethod *member = NULL;
6758 MonoReflectionParameter *param = NULL;
6759 char **names, **blobs = NULL;
6760 guint32 *types = NULL;
6761 MonoType *type = NULL;
6762 MonoObject *dbnull = NULL;
6763 MonoObject *missing = NULL;
6764 MonoMarshalSpec **mspecs;
6765 MonoMethodSignature *sig;
6766 MonoVTable *pinfo_vtable;
6769 if (!System_Reflection_ParameterInfo_array) {
6772 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6773 mono_memory_barrier ();
6774 System_Reflection_ParameterInfo = klass;
6776 klass = mono_array_class_get (klass, 1);
6777 mono_memory_barrier ();
6778 System_Reflection_ParameterInfo_array = klass;
6781 sig = mono_method_signature_checked (method, &error);
6782 if (!mono_error_ok (&error))
6783 mono_error_raise_exception (&error);
6785 if (!sig->param_count)
6786 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6788 /* Note: the cache is based on the address of the signature into the method
6789 * since we already cache MethodInfos with the method as keys.
6791 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6793 member = mono_method_get_object (domain, method, refclass);
6794 names = g_new (char *, sig->param_count);
6795 mono_method_get_param_names (method, (const char **) names);
6797 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6798 mono_method_get_marshal_info (method, mspecs);
6800 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6801 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6802 for (i = 0; i < sig->param_count; ++i) {
6803 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6804 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6805 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6806 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6807 param->PositionImpl = i;
6808 param->AttrsImpl = sig->params [i]->attrs;
6810 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6811 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6812 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6814 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6818 blobs = g_new0 (char *, sig->param_count);
6819 types = g_new0 (guint32, sig->param_count);
6820 get_default_param_value_blobs (method, blobs, types);
6823 /* Build MonoType for the type from the Constant Table */
6825 type = g_new0 (MonoType, 1);
6826 type->type = types [i];
6827 type->data.klass = NULL;
6828 if (types [i] == MONO_TYPE_CLASS)
6829 type->data.klass = mono_defaults.object_class;
6830 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6831 /* For enums, types [i] contains the base type */
6833 type->type = MONO_TYPE_VALUETYPE;
6834 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6836 type->data.klass = mono_class_from_mono_type (type);
6838 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6840 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6841 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6842 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6843 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6845 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6851 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6853 mono_array_setref (res, i, param);
6860 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6862 mono_metadata_free_marshal_spec (mspecs [i]);
6865 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6869 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6871 return mono_param_get_objects_internal (domain, method, NULL);
6875 * mono_method_body_get_object:
6876 * @domain: an app domain
6879 * Return an System.Reflection.MethodBody object representing the method @method.
6881 MonoReflectionMethodBody*
6882 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6884 static MonoClass *System_Reflection_MethodBody = NULL;
6885 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6886 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6887 MonoReflectionMethodBody *ret;
6888 MonoMethodHeader *header;
6890 guint32 method_rva, local_var_sig_token;
6892 unsigned char format, flags;
6895 /* for compatibility with .net */
6896 if (method->dynamic)
6897 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6899 if (!System_Reflection_MethodBody)
6900 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6901 if (!System_Reflection_LocalVariableInfo)
6902 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6903 if (!System_Reflection_ExceptionHandlingClause)
6904 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6906 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6908 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6909 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6910 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6911 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6914 image = method->klass->image;
6915 header = mono_method_get_header (method);
6917 if (!image->dynamic) {
6918 /* Obtain local vars signature token */
6919 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6920 ptr = mono_image_rva_map (image, method_rva);
6921 flags = *(const unsigned char *) ptr;
6922 format = flags & METHOD_HEADER_FORMAT_MASK;
6924 case METHOD_HEADER_TINY_FORMAT:
6925 local_var_sig_token = 0;
6927 case METHOD_HEADER_FAT_FORMAT:
6931 local_var_sig_token = read32 (ptr);
6934 g_assert_not_reached ();
6937 local_var_sig_token = 0; //FIXME
6939 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6941 ret->init_locals = header->init_locals;
6942 ret->max_stack = header->max_stack;
6943 ret->local_var_sig_token = local_var_sig_token;
6944 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6945 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6948 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6949 for (i = 0; i < header->num_locals; ++i) {
6950 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6951 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6952 info->is_pinned = header->locals [i]->pinned;
6953 info->local_index = i;
6954 mono_array_setref (ret->locals, i, info);
6958 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6959 for (i = 0; i < header->num_clauses; ++i) {
6960 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6961 MonoExceptionClause *clause = &header->clauses [i];
6963 info->flags = clause->flags;
6964 info->try_offset = clause->try_offset;
6965 info->try_length = clause->try_len;
6966 info->handler_offset = clause->handler_offset;
6967 info->handler_length = clause->handler_len;
6968 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6969 info->filter_offset = clause->data.filter_offset;
6970 else if (clause->data.catch_class)
6971 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6973 mono_array_setref (ret->clauses, i, info);
6976 mono_metadata_free_mh (header);
6977 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6982 * mono_get_dbnull_object:
6983 * @domain: Domain where the object lives
6985 * Returns the System.DBNull.Value singleton object
6987 * Used as the value for ParameterInfo.DefaultValue
6990 mono_get_dbnull_object (MonoDomain *domain)
6993 static MonoClassField *dbnull_value_field = NULL;
6995 if (!dbnull_value_field) {
6996 MonoClass *dbnull_klass;
6997 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6998 mono_class_init (dbnull_klass);
6999 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7000 g_assert (dbnull_value_field);
7002 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7008 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7010 guint32 param_index, i, lastp, crow = 0;
7011 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7014 MonoClass *klass = method->klass;
7015 MonoImage *image = klass->image;
7016 MonoMethodSignature *methodsig = mono_method_signature (method);
7018 MonoTableInfo *constt;
7019 MonoTableInfo *methodt;
7020 MonoTableInfo *paramt;
7022 if (!methodsig->param_count)
7025 mono_class_init (klass);
7027 if (klass->image->dynamic) {
7028 MonoReflectionMethodAux *aux;
7029 if (method->is_inflated)
7030 method = ((MonoMethodInflated*)method)->declaring;
7031 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7032 if (aux && aux->param_defaults) {
7033 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7034 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7039 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7040 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7041 constt = &image->tables [MONO_TABLE_CONSTANT];
7043 idx = mono_method_get_index (method) - 1;
7044 g_assert (idx != -1);
7046 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7047 if (idx + 1 < methodt->rows)
7048 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7050 lastp = paramt->rows + 1;
7052 for (i = param_index; i < lastp; ++i) {
7055 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7056 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7058 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7061 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7066 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7067 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7068 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7075 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7080 MonoType *basetype = type;
7085 klass = mono_class_from_mono_type (type);
7086 if (klass->valuetype) {
7087 object = mono_object_new (domain, klass);
7088 retval = ((gchar *) object + sizeof (MonoObject));
7089 if (klass->enumtype)
7090 basetype = mono_class_enum_basetype (klass);
7095 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7102 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7105 gboolean quoted = FALSE;
7107 memset (assembly, 0, sizeof (MonoAssemblyName));
7108 assembly->culture = "";
7109 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7116 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7127 /* Remove trailing whitespace */
7129 while (*s && g_ascii_isspace (*s))
7132 while (g_ascii_isspace (*p))
7135 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7137 assembly->major = strtoul (p, &s, 10);
7138 if (s == p || *s != '.')
7141 assembly->minor = strtoul (p, &s, 10);
7142 if (s == p || *s != '.')
7145 assembly->build = strtoul (p, &s, 10);
7146 if (s == p || *s != '.')
7149 assembly->revision = strtoul (p, &s, 10);
7153 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7155 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7156 assembly->culture = "";
7159 assembly->culture = p;
7160 while (*p && *p != ',') {
7164 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7166 if (strncmp (p, "null", 4) == 0) {
7171 while (*p && *p != ',') {
7174 len = (p - start + 1);
7175 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7176 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7177 g_strlcpy ((char*)assembly->public_key_token, start, len);
7180 while (*p && *p != ',')
7184 while (g_ascii_isspace (*p) || *p == ',') {
7198 * mono_reflection_parse_type:
7201 * Parse a type name as accepted by the GetType () method and output the info
7202 * extracted in the info structure.
7203 * the name param will be mangled, so, make a copy before passing it to this function.
7204 * The fields in info will be valid until the memory pointed to by name is valid.
7206 * See also mono_type_get_name () below.
7208 * Returns: 0 on parse error.
7211 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7212 MonoTypeNameParse *info)
7214 char *start, *p, *w, *temp, *last_point, *startn;
7215 int in_modifiers = 0;
7216 int isbyref = 0, rank, arity = 0, i;
7218 start = p = w = name;
7220 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7221 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7222 info->name = info->name_space = NULL;
7223 info->nested = NULL;
7224 info->modifiers = NULL;
7225 info->type_arguments = NULL;
7227 /* last_point separates the namespace from the name */
7230 while (*p == ' ') p++, start++, w++, name++;
7235 *p = 0; /* NULL terminate the name */
7237 info->nested = g_list_append (info->nested, startn);
7238 /* we have parsed the nesting namespace + name */
7242 info->name_space = start;
7244 info->name = last_point + 1;
7246 info->name_space = (char *)"";
7265 i = strtol (p, &temp, 10);
7282 info->name_space = start;
7284 info->name = last_point + 1;
7286 info->name_space = (char *)"";
7293 if (isbyref) /* only one level allowed by the spec */
7296 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7300 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7306 info->type_arguments = g_ptr_array_new ();
7307 for (i = 0; i < arity; i++) {
7308 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7309 gboolean fqname = FALSE;
7311 g_ptr_array_add (info->type_arguments, subinfo);
7318 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7321 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7322 if (fqname && (*p != ']')) {
7330 while (*p && (*p != ']'))
7338 if (g_ascii_isspace (*aname)) {
7345 !assembly_name_to_aname (&subinfo->assembly, aname))
7347 } else if (fqname && (*p == ']')) {
7351 if (i + 1 < arity) {
7371 else if (*p == '*') /* '*' means unknown lower bound */
7372 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7379 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7390 if (g_ascii_isspace (*p)) {
7397 return 0; /* missing assembly name */
7398 if (!assembly_name_to_aname (&info->assembly, p))
7404 if (info->assembly.name)
7407 // *w = 0; /* terminate class name */
7409 if (!info->name || !*info->name)
7413 /* add other consistency checks */
7418 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7420 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7424 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7426 gboolean type_resolve = FALSE;
7428 MonoImage *rootimage = image;
7430 if (info->assembly.name) {
7431 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7432 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7434 * This could happen in the AOT compiler case when the search hook is not
7437 assembly = image->assembly;
7439 /* then we must load the assembly ourselve - see #60439 */
7440 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7444 image = assembly->image;
7445 } else if (!image) {
7446 image = mono_defaults.corlib;
7449 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7450 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7451 image = mono_defaults.corlib;
7452 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7459 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7464 gboolean bounded = FALSE;
7467 image = mono_defaults.corlib;
7470 klass = mono_class_from_name_case (image, info->name_space, info->name);
7472 klass = mono_class_from_name (image, info->name_space, info->name);
7475 for (mod = info->nested; mod; mod = mod->next) {
7476 gpointer iter = NULL;
7480 mono_class_init (parent);
7482 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7484 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7487 if (strcmp (klass->name, mod->data) == 0)
7497 if (info->type_arguments) {
7498 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7499 MonoReflectionType *the_type;
7503 for (i = 0; i < info->type_arguments->len; i++) {
7504 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7506 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7507 if (!type_args [i]) {
7513 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7515 instance = mono_reflection_bind_generic_parameters (
7516 the_type, info->type_arguments->len, type_args);
7522 klass = mono_class_from_mono_type (instance);
7525 for (mod = info->modifiers; mod; mod = mod->next) {
7526 modval = GPOINTER_TO_UINT (mod->data);
7527 if (!modval) { /* byref: must be last modifier */
7528 return &klass->this_arg;
7529 } else if (modval == -1) {
7530 klass = mono_ptr_class_get (&klass->byval_arg);
7531 } else if (modval == -2) {
7533 } else { /* array rank */
7534 klass = mono_bounded_array_class_get (klass, modval, bounded);
7538 return &klass->byval_arg;
7542 * mono_reflection_get_type:
7543 * @image: a metadata context
7544 * @info: type description structure
7545 * @ignorecase: flag for case-insensitive string compares
7546 * @type_resolve: whenever type resolve was already tried
7548 * Build a MonoType from the type description in @info.
7553 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7554 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7558 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7560 MonoReflectionAssemblyBuilder *abuilder;
7564 g_assert (assembly->dynamic);
7565 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7567 /* Enumerate all modules */
7570 if (abuilder->modules) {
7571 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7572 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7573 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7579 if (!type && abuilder->loaded_modules) {
7580 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7581 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7582 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7592 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7595 MonoReflectionAssembly *assembly;
7599 if (image && image->dynamic)
7600 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7602 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7605 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7612 *type_resolve = TRUE;
7615 /* Reconstruct the type name */
7616 fullName = g_string_new ("");
7617 if (info->name_space && (info->name_space [0] != '\0'))
7618 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7620 g_string_printf (fullName, "%s", info->name);
7621 for (mod = info->nested; mod; mod = mod->next)
7622 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7624 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7626 if (assembly->assembly->dynamic)
7627 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7629 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7632 g_string_free (fullName, TRUE);
7637 mono_reflection_free_type_info (MonoTypeNameParse *info)
7639 g_list_free (info->modifiers);
7640 g_list_free (info->nested);
7642 if (info->type_arguments) {
7645 for (i = 0; i < info->type_arguments->len; i++) {
7646 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7648 mono_reflection_free_type_info (subinfo);
7649 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7653 g_ptr_array_free (info->type_arguments, TRUE);
7658 * mono_reflection_type_from_name:
7660 * @image: a metadata context (can be NULL).
7662 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7663 * it defaults to get the type from @image or, if @image is NULL or loading
7664 * from it fails, uses corlib.
7668 mono_reflection_type_from_name (char *name, MonoImage *image)
7670 MonoType *type = NULL;
7671 MonoTypeNameParse info;
7674 /* Make a copy since parse_type modifies its argument */
7675 tmp = g_strdup (name);
7677 /*g_print ("requested type %s\n", str);*/
7678 if (mono_reflection_parse_type (tmp, &info)) {
7679 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7683 mono_reflection_free_type_info (&info);
7688 * mono_reflection_get_token:
7690 * Return the metadata token of OBJ which should be an object
7691 * representing a metadata element.
7694 mono_reflection_get_token (MonoObject *obj)
7699 klass = obj->vtable->klass;
7701 if (strcmp (klass->name, "MethodBuilder") == 0) {
7702 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7704 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7705 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7706 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7708 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7709 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7710 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7712 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7713 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7714 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7715 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7716 } else if (strcmp (klass->name, "MonoType") == 0) {
7717 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7718 MonoClass *mc = mono_class_from_mono_type (type);
7719 if (!mono_class_init (mc))
7720 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7722 token = mc->type_token;
7723 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7724 strcmp (klass->name, "MonoMethod") == 0 ||
7725 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7726 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7727 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7728 if (m->method->is_inflated) {
7729 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7730 return inflated->declaring->token;
7732 token = m->method->token;
7734 } else if (strcmp (klass->name, "MonoField") == 0) {
7735 MonoReflectionField *f = (MonoReflectionField*)obj;
7737 if (is_field_on_inst (f->field)) {
7738 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7739 int field_index = f->field - dgclass->fields;
7742 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7743 obj = dgclass->field_objects [field_index];
7744 return mono_reflection_get_token (obj);
7746 token = mono_class_get_field_token (f->field);
7747 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7748 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7750 token = mono_class_get_property_token (p->property);
7751 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7752 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7754 token = mono_class_get_event_token (p->event);
7755 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7756 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7757 MonoClass *member_class = mono_object_class (p->MemberImpl);
7758 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7760 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7761 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7762 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7765 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7766 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7768 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7769 MonoException *ex = mono_get_exception_not_implemented (msg);
7771 mono_raise_exception (ex);
7778 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7780 int slen, type = t->type;
7781 MonoClass *tklass = t->data.klass;
7787 case MONO_TYPE_BOOLEAN: {
7788 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7793 case MONO_TYPE_CHAR:
7795 case MONO_TYPE_I2: {
7796 guint16 *val = g_malloc (sizeof (guint16));
7801 #if SIZEOF_VOID_P == 4
7807 case MONO_TYPE_I4: {
7808 guint32 *val = g_malloc (sizeof (guint32));
7813 #if SIZEOF_VOID_P == 8
7814 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7818 case MONO_TYPE_I8: {
7819 guint64 *val = g_malloc (sizeof (guint64));
7824 case MONO_TYPE_R8: {
7825 double *val = g_malloc (sizeof (double));
7830 case MONO_TYPE_VALUETYPE:
7831 if (t->data.klass->enumtype) {
7832 type = mono_class_enum_basetype (t->data.klass)->type;
7835 MonoClass *k = t->data.klass;
7837 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7838 guint64 *val = g_malloc (sizeof (guint64));
7844 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7847 case MONO_TYPE_STRING:
7848 if (*p == (char)0xFF) {
7852 slen = mono_metadata_decode_value (p, &p);
7854 return mono_string_new_len (mono_domain_get (), p, slen);
7855 case MONO_TYPE_CLASS: {
7858 if (*p == (char)0xFF) {
7863 slen = mono_metadata_decode_value (p, &p);
7864 n = g_memdup (p, slen + 1);
7866 t = mono_reflection_type_from_name (n, image);
7868 g_warning ("Cannot load type '%s'", n);
7872 return mono_type_get_object (mono_domain_get (), t);
7876 case MONO_TYPE_OBJECT: {
7879 MonoClass *subc = NULL;
7884 } else if (subt == 0x0E) {
7885 type = MONO_TYPE_STRING;
7887 } else if (subt == 0x1D) {
7888 MonoType simple_type = {{0}};
7892 type = MONO_TYPE_SZARRAY;
7893 if (etype == 0x50) {
7894 tklass = mono_defaults.systemtype_class;
7897 /* See Partition II, Appendix B3 */
7898 etype = MONO_TYPE_OBJECT;
7899 simple_type.type = etype;
7900 tklass = mono_class_from_mono_type (&simple_type);
7903 } else if (subt == 0x55) {
7906 slen = mono_metadata_decode_value (p, &p);
7907 n = g_memdup (p, slen + 1);
7909 t = mono_reflection_type_from_name (n, image);
7911 g_error ("Cannot load type '%s'", n);
7914 subc = mono_class_from_mono_type (t);
7915 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7916 MonoType simple_type = {{0}};
7917 simple_type.type = subt;
7918 subc = mono_class_from_mono_type (&simple_type);
7920 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7922 val = load_cattr_value (image, &subc->byval_arg, p, end);
7923 obj = mono_object_new (mono_domain_get (), subc);
7924 g_assert (!subc->has_references);
7925 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7929 case MONO_TYPE_SZARRAY: {
7931 guint32 i, alen, basetype;
7934 if (alen == 0xffffffff) {
7938 arr = mono_array_new (mono_domain_get(), tklass, alen);
7939 basetype = tklass->byval_arg.type;
7940 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7941 basetype = mono_class_enum_basetype (tklass)->type;
7946 case MONO_TYPE_BOOLEAN:
7947 for (i = 0; i < alen; i++) {
7948 MonoBoolean val = *p++;
7949 mono_array_set (arr, MonoBoolean, i, val);
7952 case MONO_TYPE_CHAR:
7955 for (i = 0; i < alen; i++) {
7956 guint16 val = read16 (p);
7957 mono_array_set (arr, guint16, i, val);
7964 for (i = 0; i < alen; i++) {
7965 guint32 val = read32 (p);
7966 mono_array_set (arr, guint32, i, val);
7971 for (i = 0; i < alen; i++) {
7974 mono_array_set (arr, double, i, val);
7980 for (i = 0; i < alen; i++) {
7981 guint64 val = read64 (p);
7982 mono_array_set (arr, guint64, i, val);
7986 case MONO_TYPE_CLASS:
7987 case MONO_TYPE_OBJECT:
7988 case MONO_TYPE_STRING:
7989 for (i = 0; i < alen; i++) {
7990 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7991 mono_array_setref (arr, i, item);
7995 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8001 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8007 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8009 static MonoClass *klass;
8010 static MonoMethod *ctor;
8012 void *params [2], *unboxed;
8015 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8017 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8019 params [0] = mono_type_get_object (mono_domain_get (), t);
8021 retval = mono_object_new (mono_domain_get (), klass);
8022 unboxed = mono_object_unbox (retval);
8023 mono_runtime_invoke (ctor, unboxed, params, NULL);
8029 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8031 static MonoClass *klass;
8032 static MonoMethod *ctor;
8034 void *unboxed, *params [2];
8037 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8039 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8042 params [1] = typedarg;
8043 retval = mono_object_new (mono_domain_get (), klass);
8044 unboxed = mono_object_unbox (retval);
8045 mono_runtime_invoke (ctor, unboxed, params, NULL);
8051 type_is_reference (MonoType *type)
8053 switch (type->type) {
8054 case MONO_TYPE_BOOLEAN:
8055 case MONO_TYPE_CHAR:
8068 case MONO_TYPE_VALUETYPE:
8076 free_param_data (MonoMethodSignature *sig, void **params) {
8078 for (i = 0; i < sig->param_count; ++i) {
8079 if (!type_is_reference (sig->params [i]))
8080 g_free (params [i]);
8085 * Find the field index in the metadata FieldDef table.
8088 find_field_index (MonoClass *klass, MonoClassField *field) {
8091 for (i = 0; i < klass->field.count; ++i) {
8092 if (field == &klass->fields [i])
8093 return klass->field.first + 1 + i;
8099 * Find the property index in the metadata Property table.
8102 find_property_index (MonoClass *klass, MonoProperty *property) {
8105 for (i = 0; i < klass->ext->property.count; ++i) {
8106 if (property == &klass->ext->properties [i])
8107 return klass->ext->property.first + 1 + i;
8113 * Find the event index in the metadata Event table.
8116 find_event_index (MonoClass *klass, MonoEvent *event) {
8119 for (i = 0; i < klass->ext->event.count; ++i) {
8120 if (event == &klass->ext->events [i])
8121 return klass->ext->event.first + 1 + i;
8127 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8129 const char *p = (const char*)data;
8131 guint32 i, j, num_named;
8133 void *params_buf [32];
8135 MonoMethodSignature *sig;
8137 mono_error_init (error);
8139 mono_class_init (method->klass);
8141 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8142 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8147 attr = mono_object_new (mono_domain_get (), method->klass);
8148 mono_runtime_invoke (method, attr, NULL, NULL);
8152 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8155 /*g_print ("got attr %s\n", method->klass->name);*/
8157 sig = mono_method_signature (method);
8158 if (sig->param_count < 32)
8159 params = params_buf;
8161 /* Allocate using GC so it gets GC tracking */
8162 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8166 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8167 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8171 attr = mono_object_new (mono_domain_get (), method->klass);
8172 mono_runtime_invoke (method, attr, params, NULL);
8173 free_param_data (method->signature, params);
8174 num_named = read16 (named);
8176 for (j = 0; j < num_named; j++) {
8178 char *name, named_type, data_type;
8179 named_type = *named++;
8180 data_type = *named++; /* type of data */
8181 if (data_type == MONO_TYPE_SZARRAY)
8182 data_type = *named++;
8183 if (data_type == MONO_TYPE_ENUM) {
8186 type_len = mono_metadata_decode_blob_size (named, &named);
8187 type_name = g_malloc (type_len + 1);
8188 memcpy (type_name, named, type_len);
8189 type_name [type_len] = 0;
8191 /* FIXME: lookup the type and check type consistency */
8194 name_len = mono_metadata_decode_blob_size (named, &named);
8195 name = g_malloc (name_len + 1);
8196 memcpy (name, named, name_len);
8197 name [name_len] = 0;
8199 if (named_type == 0x53) {
8200 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8201 void *val = load_cattr_value (image, field->type, named, &named);
8202 mono_field_set_value (attr, field, val);
8203 if (!type_is_reference (field->type))
8205 } else if (named_type == 0x54) {
8208 MonoType *prop_type;
8210 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8211 /* can we have more that 1 arg in a custom attr named property? */
8212 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8213 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8214 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8215 mono_property_set_value (prop, attr, pparams, NULL);
8216 if (!type_is_reference (prop_type))
8217 g_free (pparams [0]);
8222 if (params != params_buf)
8223 mono_gc_free_fixed (params);
8229 * mono_reflection_create_custom_attr_data_args:
8231 * Create an array of typed and named arguments from the cattr blob given by DATA.
8232 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8233 * NAMED_ARG_INFO will contain information about the named arguments.
8236 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
8238 MonoArray *typedargs, *namedargs;
8239 MonoClass *attrklass;
8241 const char *p = (const char*)data;
8243 guint32 i, j, num_named;
8244 CattrNamedArg *arginfo = NULL;
8248 *named_arg_info = NULL;
8250 mono_error_init (error);
8252 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8253 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8257 mono_class_init (method->klass);
8259 domain = mono_domain_get ();
8261 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8264 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8268 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8272 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8273 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8274 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8275 mono_array_setref (typedargs, i, obj);
8277 if (!type_is_reference (mono_method_signature (method)->params [i]))
8282 num_named = read16 (named);
8283 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8285 attrklass = method->klass;
8287 arginfo = g_new0 (CattrNamedArg, num_named);
8288 *named_arg_info = arginfo;
8290 for (j = 0; j < num_named; j++) {
8292 char *name, named_type, data_type;
8293 named_type = *named++;
8294 data_type = *named++; /* type of data */
8295 if (data_type == MONO_TYPE_SZARRAY)
8296 data_type = *named++;
8297 if (data_type == MONO_TYPE_ENUM) {
8300 type_len = mono_metadata_decode_blob_size (named, &named);
8301 type_name = g_malloc (type_len + 1);
8302 memcpy (type_name, named, type_len);
8303 type_name [type_len] = 0;
8305 /* FIXME: lookup the type and check type consistency */
8308 name_len = mono_metadata_decode_blob_size (named, &named);
8309 name = g_malloc (name_len + 1);
8310 memcpy (name, named, name_len);
8311 name [name_len] = 0;
8313 if (named_type == 0x53) {
8315 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8318 arginfo [j].type = field->type;
8319 arginfo [j].field = field;
8321 val = load_cattr_value (image, field->type, named, &named);
8322 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8323 mono_array_setref (namedargs, j, obj);
8324 if (!type_is_reference (field->type))
8326 } else if (named_type == 0x54) {
8328 MonoType *prop_type;
8329 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8332 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8333 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8335 arginfo [j].type = prop_type;
8336 arginfo [j].prop = prop;
8338 val = load_cattr_value (image, prop_type, named, &named);
8339 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8340 mono_array_setref (namedargs, j, obj);
8341 if (!type_is_reference (prop_type))
8347 *typed_args = typedargs;
8348 *named_args = namedargs;
8352 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8355 MonoArray *typedargs, *namedargs;
8358 CattrNamedArg *arginfo;
8368 image = assembly->assembly->image;
8369 method = ref_method->method;
8370 domain = mono_object_domain (ref_method);
8372 if (!mono_class_init (method->klass))
8373 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8375 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8376 if (!mono_error_ok (&error))
8377 mono_error_raise_exception (&error);
8378 if (mono_loader_get_last_error ())
8379 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8381 if (!typedargs || !namedargs)
8384 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8385 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8386 MonoObject *typedarg;
8388 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8389 mono_array_setref (typedargs, i, typedarg);
8392 for (i = 0; i < mono_array_length (namedargs); ++i) {
8393 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8394 MonoObject *typedarg, *namedarg, *minfo;
8396 if (arginfo [i].prop)
8397 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8399 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8401 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8402 namedarg = create_cattr_named_arg (minfo, typedarg);
8404 mono_array_setref (namedargs, i, namedarg);
8407 *ctor_args = typedargs;
8408 *named_args = namedargs;
8412 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8414 static MonoMethod *ctor;
8419 g_assert (image->assembly);
8422 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8424 domain = mono_domain_get ();
8425 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8426 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8427 params [1] = mono_assembly_get_object (domain, image->assembly);
8428 params [2] = (gpointer)&cattr->data;
8429 params [3] = &cattr->data_size;
8430 mono_runtime_invoke (ctor, attr, params, NULL);
8435 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8441 mono_error_init (error);
8444 for (i = 0; i < cinfo->num_attrs; ++i) {
8445 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8449 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8451 for (i = 0; i < cinfo->num_attrs; ++i) {
8452 if (!cinfo->attrs [i].ctor)
8453 /* The cattr type is not finished yet */
8454 /* We should include the type name but cinfo doesn't contain it */
8455 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8456 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8457 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8458 if (!mono_error_ok (error))
8460 mono_array_setref (result, n, attr);
8468 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8472 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8476 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8482 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8483 for (i = 0; i < cinfo->num_attrs; ++i) {
8484 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8485 mono_array_setref (result, i, attr);
8491 * mono_custom_attrs_from_index:
8493 * Returns: NULL if no attributes are found or if a loading error occurs.
8496 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8498 guint32 mtoken, i, len;
8499 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8501 MonoCustomAttrInfo *ainfo;
8502 GList *tmp, *list = NULL;
8505 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8507 i = mono_metadata_custom_attrs_from_index (image, idx);
8511 while (i < ca->rows) {
8512 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8514 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8517 len = g_list_length (list);
8520 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8521 ainfo->num_attrs = len;
8522 ainfo->image = image;
8523 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8524 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8525 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8526 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8527 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8528 mtoken |= MONO_TOKEN_METHOD_DEF;
8530 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8531 mtoken |= MONO_TOKEN_MEMBER_REF;
8534 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8537 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8538 if (!ainfo->attrs [i].ctor) {
8539 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8545 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8546 /*FIXME raising an exception here doesn't make any sense*/
8547 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8552 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8553 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8554 ainfo->attrs [i].data = (guchar*)data;
8562 mono_custom_attrs_from_method (MonoMethod *method)
8567 * An instantiated method has the same cattrs as the generic method definition.
8569 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8570 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8572 if (method->is_inflated)
8573 method = ((MonoMethodInflated *) method)->declaring;
8575 if (method->dynamic || method->klass->image->dynamic)
8576 return lookup_custom_attr (method->klass->image, method);
8579 /* Synthetic methods */
8582 idx = mono_method_get_index (method);
8583 idx <<= MONO_CUSTOM_ATTR_BITS;
8584 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8585 return mono_custom_attrs_from_index (method->klass->image, idx);
8589 mono_custom_attrs_from_class (MonoClass *klass)
8593 if (klass->generic_class)
8594 klass = klass->generic_class->container_class;
8596 if (klass->image->dynamic)
8597 return lookup_custom_attr (klass->image, klass);
8599 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8600 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8601 idx <<= MONO_CUSTOM_ATTR_BITS;
8602 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8604 idx = mono_metadata_token_index (klass->type_token);
8605 idx <<= MONO_CUSTOM_ATTR_BITS;
8606 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8608 return mono_custom_attrs_from_index (klass->image, idx);
8612 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8616 if (assembly->image->dynamic)
8617 return lookup_custom_attr (assembly->image, assembly);
8618 idx = 1; /* there is only one assembly */
8619 idx <<= MONO_CUSTOM_ATTR_BITS;
8620 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8621 return mono_custom_attrs_from_index (assembly->image, idx);
8624 static MonoCustomAttrInfo*
8625 mono_custom_attrs_from_module (MonoImage *image)
8630 return lookup_custom_attr (image, image);
8631 idx = 1; /* there is only one module */
8632 idx <<= MONO_CUSTOM_ATTR_BITS;
8633 idx |= MONO_CUSTOM_ATTR_MODULE;
8634 return mono_custom_attrs_from_index (image, idx);
8638 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8642 if (klass->image->dynamic) {
8643 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8644 return lookup_custom_attr (klass->image, property);
8646 idx = find_property_index (klass, property);
8647 idx <<= MONO_CUSTOM_ATTR_BITS;
8648 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8649 return mono_custom_attrs_from_index (klass->image, idx);
8653 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8657 if (klass->image->dynamic) {
8658 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8659 return lookup_custom_attr (klass->image, event);
8661 idx = find_event_index (klass, event);
8662 idx <<= MONO_CUSTOM_ATTR_BITS;
8663 idx |= MONO_CUSTOM_ATTR_EVENT;
8664 return mono_custom_attrs_from_index (klass->image, idx);
8668 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8671 if (klass->image->dynamic) {
8672 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8673 return lookup_custom_attr (klass->image, field);
8675 idx = find_field_index (klass, field);
8676 idx <<= MONO_CUSTOM_ATTR_BITS;
8677 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8678 return mono_custom_attrs_from_index (klass->image, idx);
8682 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8685 guint32 i, idx, method_index;
8686 guint32 param_list, param_last, param_pos, found;
8688 MonoReflectionMethodAux *aux;
8691 * An instantiated method has the same cattrs as the generic method definition.
8693 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8694 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8696 if (method->is_inflated)
8697 method = ((MonoMethodInflated *) method)->declaring;
8699 if (method->klass->image->dynamic) {
8700 MonoCustomAttrInfo *res, *ainfo;
8703 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8704 if (!aux || !aux->param_cattr)
8707 /* Need to copy since it will be freed later */
8708 ainfo = aux->param_cattr [param];
8711 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8712 res = g_malloc0 (size);
8713 memcpy (res, ainfo, size);
8717 image = method->klass->image;
8718 method_index = mono_method_get_index (method);
8721 ca = &image->tables [MONO_TABLE_METHOD];
8723 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8724 if (method_index == ca->rows) {
8725 ca = &image->tables [MONO_TABLE_PARAM];
8726 param_last = ca->rows + 1;
8728 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8729 ca = &image->tables [MONO_TABLE_PARAM];
8732 for (i = param_list; i < param_last; ++i) {
8733 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8734 if (param_pos == param) {
8742 idx <<= MONO_CUSTOM_ATTR_BITS;
8743 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8744 return mono_custom_attrs_from_index (image, idx);
8748 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8752 for (i = 0; i < ainfo->num_attrs; ++i) {
8753 klass = ainfo->attrs [i].ctor->klass;
8754 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8761 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8768 for (i = 0; i < ainfo->num_attrs; ++i) {
8769 klass = ainfo->attrs [i].ctor->klass;
8770 if (mono_class_has_parent (klass, attr_klass)) {
8775 if (attr_index == -1)
8778 attrs = mono_custom_attrs_construct (ainfo);
8780 return mono_array_get (attrs, MonoObject*, attr_index);
8786 * mono_reflection_get_custom_attrs_info:
8787 * @obj: a reflection object handle
8789 * Return the custom attribute info for attributes defined for the
8790 * reflection handle @obj. The objects.
8792 * FIXME this function leaks like a sieve for SRE objects.
8795 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8798 MonoCustomAttrInfo *cinfo = NULL;
8800 klass = obj->vtable->klass;
8801 if (klass == mono_defaults.monotype_class) {
8802 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8803 klass = mono_class_from_mono_type (type);
8804 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8805 cinfo = mono_custom_attrs_from_class (klass);
8806 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8807 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8808 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8809 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8810 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8811 cinfo = mono_custom_attrs_from_module (module->image);
8812 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8813 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8814 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8815 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8816 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8817 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8818 } else if (strcmp ("MonoField", klass->name) == 0) {
8819 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8820 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8821 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8822 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8823 cinfo = mono_custom_attrs_from_method (rmethod->method);
8824 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8825 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8826 cinfo = mono_custom_attrs_from_method (rmethod->method);
8827 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8828 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8829 MonoClass *member_class = mono_object_class (param->MemberImpl);
8830 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8831 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8832 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8833 } else if (is_sr_mono_property (member_class)) {
8834 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8836 if (!(method = prop->property->get))
8837 method = prop->property->set;
8840 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8842 #ifndef DISABLE_REFLECTION_EMIT
8843 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8844 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8845 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8846 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8847 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8848 MonoMethod *method = NULL;
8849 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8850 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8851 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8852 method = ((MonoReflectionMethod *)c->cb)->method;
8854 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));
8856 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8860 char *type_name = mono_type_get_full_name (member_class);
8861 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8862 MonoException *ex = mono_get_exception_not_supported (msg);
8865 mono_raise_exception (ex);
8867 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8868 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8869 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8870 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8871 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8872 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8873 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8874 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8875 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8876 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8877 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8878 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8879 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8880 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8881 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8882 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8883 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8884 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8885 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8886 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8887 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8888 } else { /* handle other types here... */
8889 g_error ("get custom attrs not yet supported for %s", klass->name);
8896 * mono_reflection_get_custom_attrs_by_type:
8897 * @obj: a reflection object handle
8899 * Return an array with all the custom attributes defined of the
8900 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8901 * of that type are returned. The objects are fully build. Return NULL if a loading error
8905 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8908 MonoCustomAttrInfo *cinfo;
8910 mono_error_init (error);
8912 cinfo = mono_reflection_get_custom_attrs_info (obj);
8914 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8916 mono_custom_attrs_free (cinfo);
8918 if (mono_loader_get_last_error ())
8920 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8927 * mono_reflection_get_custom_attrs:
8928 * @obj: a reflection object handle
8930 * Return an array with all the custom attributes defined of the
8931 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8935 mono_reflection_get_custom_attrs (MonoObject *obj)
8939 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8943 * mono_reflection_get_custom_attrs_data:
8944 * @obj: a reflection obj handle
8946 * Returns an array of System.Reflection.CustomAttributeData,
8947 * which include information about attributes reflected on
8948 * types loaded using the Reflection Only methods
8951 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8954 MonoCustomAttrInfo *cinfo;
8956 cinfo = mono_reflection_get_custom_attrs_info (obj);
8958 result = mono_custom_attrs_data_construct (cinfo);
8960 mono_custom_attrs_free (cinfo);
8962 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8967 static MonoReflectionType*
8968 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8970 static MonoMethod *method_get_underlying_system_type = NULL;
8971 MonoMethod *usertype_method;
8973 if (!method_get_underlying_system_type)
8974 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8975 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8976 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8981 is_corlib_type (MonoClass *class)
8983 return class->image == mono_defaults.corlib;
8986 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8987 static MonoClass *cached_class; \
8989 return cached_class == _class; \
8990 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8991 cached_class = _class; \
8998 #ifndef DISABLE_REFLECTION_EMIT
9000 is_sre_array (MonoClass *class)
9002 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9006 is_sre_byref (MonoClass *class)
9008 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9012 is_sre_pointer (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9018 is_sre_generic_instance (MonoClass *class)
9020 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9024 is_sre_type_builder (MonoClass *class)
9026 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9030 is_sre_method_builder (MonoClass *class)
9032 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9036 is_sre_ctor_builder (MonoClass *class)
9038 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9042 is_sre_field_builder (MonoClass *class)
9044 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9048 is_sre_method_on_tb_inst (MonoClass *class)
9050 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9054 is_sre_ctor_on_tb_inst (MonoClass *class)
9056 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9060 mono_reflection_type_get_handle (MonoReflectionType* ref)
9068 if (is_usertype (ref)) {
9069 ref = mono_reflection_type_get_underlying_system_type (ref);
9070 if (ref == NULL || is_usertype (ref))
9076 class = mono_object_class (ref);
9078 if (is_sre_array (class)) {
9080 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9081 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9083 if (sre_array->rank == 0) //single dimentional array
9084 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9086 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9087 sre_array->type.type = res;
9089 } else if (is_sre_byref (class)) {
9091 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9092 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9094 res = &mono_class_from_mono_type (base)->this_arg;
9095 sre_byref->type.type = res;
9097 } else if (is_sre_pointer (class)) {
9099 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9100 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9102 res = &mono_ptr_class_get (base)->byval_arg;
9103 sre_pointer->type.type = res;
9105 } else if (is_sre_generic_instance (class)) {
9106 MonoType *res, **types;
9107 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9110 count = mono_array_length (gclass->type_arguments);
9111 types = g_new0 (MonoType*, count);
9112 for (i = 0; i < count; ++i) {
9113 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9114 types [i] = mono_reflection_type_get_handle (t);
9121 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9124 gclass->type.type = res;
9128 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9135 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9137 mono_reflection_type_get_handle (type);
9141 mono_reflection_register_with_runtime (MonoReflectionType *type)
9143 MonoType *res = mono_reflection_type_get_handle (type);
9144 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9148 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9150 class = mono_class_from_mono_type (res);
9152 mono_loader_lock (); /*same locking as mono_type_get_object*/
9153 mono_domain_lock (domain);
9155 if (!class->image->dynamic) {
9156 mono_class_setup_supertypes (class);
9158 if (!domain->type_hash)
9159 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9160 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9161 mono_g_hash_table_insert (domain->type_hash, res, type);
9163 mono_domain_unlock (domain);
9164 mono_loader_unlock ();
9168 * LOCKING: Assumes the loader lock is held.
9170 static MonoMethodSignature*
9171 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9172 MonoMethodSignature *sig;
9175 count = parameters? mono_array_length (parameters): 0;
9177 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9178 sig->param_count = count;
9179 sig->sentinelpos = -1; /* FIXME */
9180 for (i = 0; i < count; ++i)
9181 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9186 * LOCKING: Assumes the loader lock is held.
9188 static MonoMethodSignature*
9189 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9190 MonoMethodSignature *sig;
9192 sig = parameters_to_signature (image, ctor->parameters);
9193 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9194 sig->ret = &mono_defaults.void_class->byval_arg;
9199 * LOCKING: Assumes the loader lock is held.
9201 static MonoMethodSignature*
9202 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9203 MonoMethodSignature *sig;
9205 sig = parameters_to_signature (image, method->parameters);
9206 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9207 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9208 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9212 static MonoMethodSignature*
9213 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9214 MonoMethodSignature *sig;
9216 sig = parameters_to_signature (NULL, method->parameters);
9217 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9218 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9219 sig->generic_param_count = 0;
9224 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9226 MonoClass *klass = mono_object_class (prop);
9227 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9228 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9229 *name = mono_string_to_utf8 (pb->name);
9230 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9232 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9233 *name = g_strdup (p->property->name);
9234 if (p->property->get)
9235 *type = mono_method_signature (p->property->get)->ret;
9237 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9242 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9244 MonoClass *klass = mono_object_class (field);
9245 if (strcmp (klass->name, "FieldBuilder") == 0) {
9246 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9247 *name = mono_string_to_utf8 (fb->name);
9248 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9250 MonoReflectionField *f = (MonoReflectionField *)field;
9251 *name = g_strdup (mono_field_get_name (f->field));
9252 *type = f->field->type;
9256 #else /* DISABLE_REFLECTION_EMIT */
9259 mono_reflection_register_with_runtime (MonoReflectionType *type)
9265 is_sre_type_builder (MonoClass *class)
9271 is_sre_generic_instance (MonoClass *class)
9277 init_type_builder_generics (MonoObject *type)
9281 #endif /* !DISABLE_REFLECTION_EMIT */
9285 is_sr_mono_field (MonoClass *class)
9287 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9291 is_sr_mono_property (MonoClass *class)
9293 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9297 is_sr_mono_method (MonoClass *class)
9299 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9303 is_sr_mono_cmethod (MonoClass *class)
9305 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9309 is_sr_mono_generic_method (MonoClass *class)
9311 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9315 is_sr_mono_generic_cmethod (MonoClass *class)
9317 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9321 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9323 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9327 is_usertype (MonoReflectionType *ref)
9329 MonoClass *class = mono_object_class (ref);
9330 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9333 static MonoReflectionType*
9334 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9336 if (!type || type->type)
9339 if (is_usertype (type)) {
9340 type = mono_reflection_type_get_underlying_system_type (type);
9341 if (is_usertype (type))
9342 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9348 * Encode a value in a custom attribute stream of bytes.
9349 * The value to encode is either supplied as an object in argument val
9350 * (valuetypes are boxed), or as a pointer to the data in the
9352 * @type represents the type of the value
9353 * @buffer is the start of the buffer
9354 * @p the current position in the buffer
9355 * @buflen contains the size of the buffer and is used to return the new buffer size
9356 * if this needs to be realloced.
9357 * @retbuffer and @retp return the start and the position of the buffer
9360 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9362 MonoTypeEnum simple_type;
9364 if ((p-buffer) + 10 >= *buflen) {
9367 newbuf = g_realloc (buffer, *buflen);
9368 p = newbuf + (p-buffer);
9372 argval = ((char*)arg + sizeof (MonoObject));
9373 simple_type = type->type;
9375 switch (simple_type) {
9376 case MONO_TYPE_BOOLEAN:
9381 case MONO_TYPE_CHAR:
9384 swap_with_size (p, argval, 2, 1);
9390 swap_with_size (p, argval, 4, 1);
9394 swap_with_size (p, argval, 8, 1);
9399 swap_with_size (p, argval, 8, 1);
9402 case MONO_TYPE_VALUETYPE:
9403 if (type->data.klass->enumtype) {
9404 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9407 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9410 case MONO_TYPE_STRING: {
9417 str = mono_string_to_utf8 ((MonoString*)arg);
9418 slen = strlen (str);
9419 if ((p-buffer) + 10 + slen >= *buflen) {
9423 newbuf = g_realloc (buffer, *buflen);
9424 p = newbuf + (p-buffer);
9427 mono_metadata_encode_value (slen, p, &p);
9428 memcpy (p, str, slen);
9433 case MONO_TYPE_CLASS: {
9441 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9442 slen = strlen (str);
9443 if ((p-buffer) + 10 + slen >= *buflen) {
9447 newbuf = g_realloc (buffer, *buflen);
9448 p = newbuf + (p-buffer);
9451 mono_metadata_encode_value (slen, p, &p);
9452 memcpy (p, str, slen);
9457 case MONO_TYPE_SZARRAY: {
9459 MonoClass *eclass, *arg_eclass;
9462 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9465 len = mono_array_length ((MonoArray*)arg);
9467 *p++ = (len >> 8) & 0xff;
9468 *p++ = (len >> 16) & 0xff;
9469 *p++ = (len >> 24) & 0xff;
9471 *retbuffer = buffer;
9472 eclass = type->data.klass;
9473 arg_eclass = mono_object_class (arg)->element_class;
9476 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9477 eclass = mono_defaults.object_class;
9479 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9480 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9481 int elsize = mono_class_array_element_size (arg_eclass);
9482 for (i = 0; i < len; ++i) {
9483 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9486 } else if (eclass->valuetype && arg_eclass->valuetype) {
9487 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9488 int elsize = mono_class_array_element_size (eclass);
9489 for (i = 0; i < len; ++i) {
9490 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9494 for (i = 0; i < len; ++i) {
9495 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9500 case MONO_TYPE_OBJECT: {
9506 * The parameter type is 'object' but the type of the actual
9507 * argument is not. So we have to add type information to the blob
9508 * too. This is completely undocumented in the spec.
9512 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9517 klass = mono_object_class (arg);
9519 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9522 } else if (klass->enumtype) {
9524 } else if (klass == mono_defaults.string_class) {
9525 simple_type = MONO_TYPE_STRING;
9528 } else if (klass->rank == 1) {
9530 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9531 /* See Partition II, Appendix B3 */
9534 *p++ = klass->element_class->byval_arg.type;
9535 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9537 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9538 *p++ = simple_type = klass->byval_arg.type;
9541 g_error ("unhandled type in custom attr");
9543 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9544 slen = strlen (str);
9545 if ((p-buffer) + 10 + slen >= *buflen) {
9549 newbuf = g_realloc (buffer, *buflen);
9550 p = newbuf + (p-buffer);
9553 mono_metadata_encode_value (slen, p, &p);
9554 memcpy (p, str, slen);
9557 simple_type = mono_class_enum_basetype (klass)->type;
9561 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9564 *retbuffer = buffer;
9568 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9570 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9571 char *str = type_get_qualified_name (type, NULL);
9572 int slen = strlen (str);
9576 * This seems to be optional...
9579 mono_metadata_encode_value (slen, p, &p);
9580 memcpy (p, str, slen);
9583 } else if (type->type == MONO_TYPE_OBJECT) {
9585 } else if (type->type == MONO_TYPE_CLASS) {
9586 /* it should be a type: encode_cattr_value () has the check */
9589 mono_metadata_encode_value (type->type, p, &p);
9590 if (type->type == MONO_TYPE_SZARRAY)
9591 /* See the examples in Partition VI, Annex B */
9592 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9598 #ifndef DISABLE_REFLECTION_EMIT
9600 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9603 /* Preallocate a large enough buffer */
9604 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9605 char *str = type_get_qualified_name (type, NULL);
9608 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9609 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9615 len += strlen (name);
9617 if ((p-buffer) + 20 + len >= *buflen) {
9621 newbuf = g_realloc (buffer, *buflen);
9622 p = newbuf + (p-buffer);
9626 encode_field_or_prop_type (type, p, &p);
9628 len = strlen (name);
9629 mono_metadata_encode_value (len, p, &p);
9630 memcpy (p, name, len);
9632 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9634 *retbuffer = buffer;
9638 * mono_reflection_get_custom_attrs_blob:
9639 * @ctor: custom attribute constructor
9640 * @ctorArgs: arguments o the constructor
9646 * Creates the blob of data that needs to be saved in the metadata and that represents
9647 * the custom attributed described by @ctor, @ctorArgs etc.
9648 * Returns: a Byte array representing the blob of data.
9651 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9654 MonoMethodSignature *sig;
9659 MONO_ARCH_SAVE_REGS;
9661 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9662 /* sig is freed later so allocate it in the heap */
9663 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9665 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9668 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9670 p = buffer = g_malloc (buflen);
9671 /* write the prolog */
9674 for (i = 0; i < sig->param_count; ++i) {
9675 arg = mono_array_get (ctorArgs, MonoObject*, i);
9676 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9680 i += mono_array_length (properties);
9682 i += mono_array_length (fields);
9684 *p++ = (i >> 8) & 0xff;
9687 for (i = 0; i < mono_array_length (properties); ++i) {
9691 prop = mono_array_get (properties, gpointer, i);
9692 get_prop_name_and_type (prop, &pname, &ptype);
9693 *p++ = 0x54; /* PROPERTY signature */
9694 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9701 for (i = 0; i < mono_array_length (fields); ++i) {
9705 field = mono_array_get (fields, gpointer, i);
9706 get_field_name_and_type (field, &fname, &ftype);
9707 *p++ = 0x53; /* FIELD signature */
9708 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9713 g_assert (p - buffer <= buflen);
9714 buflen = p - buffer;
9715 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9716 p = mono_array_addr (result, char, 0);
9717 memcpy (p, buffer, buflen);
9719 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9725 * mono_reflection_setup_internal_class:
9726 * @tb: a TypeBuilder object
9728 * Creates a MonoClass that represents the TypeBuilder.
9729 * This is a trick that lets us simplify a lot of reflection code
9730 * (and will allow us to support Build and Run assemblies easier).
9733 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9736 MonoClass *klass, *parent;
9738 MONO_ARCH_SAVE_REGS;
9740 RESOLVE_TYPE (tb->parent);
9742 mono_loader_lock ();
9745 /* check so we can compile corlib correctly */
9746 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9747 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9748 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9750 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9756 /* the type has already being created: it means we just have to change the parent */
9757 if (tb->type.type) {
9758 klass = mono_class_from_mono_type (tb->type.type);
9759 klass->parent = NULL;
9760 /* fool mono_class_setup_parent */
9761 klass->supertypes = NULL;
9762 mono_class_setup_parent (klass, parent);
9763 mono_class_setup_mono_type (klass);
9764 mono_loader_unlock ();
9768 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9770 klass->image = &tb->module->dynamic_image->image;
9772 klass->inited = 1; /* we lie to the runtime */
9773 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9774 if (!mono_error_ok (&error))
9776 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9777 if (!mono_error_ok (&error))
9779 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9780 klass->flags = tb->attrs;
9782 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9784 klass->element_class = klass;
9786 if (mono_class_get_ref_info (klass) == NULL) {
9788 mono_class_set_ref_info (klass, tb);
9790 /* Put into cache so mono_class_get () will find it.
9791 Skip nested types as those should not be available on the global scope. */
9792 if (!tb->nesting_type) {
9793 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9795 klass->image->reflection_info_unregister_classes =
9796 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9799 g_assert (mono_class_get_ref_info (klass) == tb);
9802 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9803 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9805 if (parent != NULL) {
9806 mono_class_setup_parent (klass, parent);
9807 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9808 const char *old_n = klass->name;
9809 /* trick to get relative numbering right when compiling corlib */
9810 klass->name = "BuildingObject";
9811 mono_class_setup_parent (klass, mono_defaults.object_class);
9812 klass->name = old_n;
9815 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9816 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9817 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9818 klass->instance_size = sizeof (MonoObject);
9819 klass->size_inited = 1;
9820 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9823 mono_class_setup_mono_type (klass);
9825 mono_class_setup_supertypes (klass);
9828 * FIXME: handle interfaces.
9831 tb->type.type = &klass->byval_arg;
9833 if (tb->nesting_type) {
9834 g_assert (tb->nesting_type->type);
9835 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9838 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9840 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9842 mono_loader_unlock ();
9846 mono_loader_unlock ();
9847 mono_error_raise_exception (&error);
9851 * mono_reflection_setup_generic_class:
9852 * @tb: a TypeBuilder object
9854 * Setup the generic class before adding the first generic parameter.
9857 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9862 * mono_reflection_create_generic_class:
9863 * @tb: a TypeBuilder object
9865 * Creates the generic class after all generic parameters have been added.
9868 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9873 MONO_ARCH_SAVE_REGS;
9875 klass = mono_class_from_mono_type (tb->type.type);
9877 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9879 if (klass->generic_container || (count == 0))
9882 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9884 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9886 klass->generic_container->owner.klass = klass;
9887 klass->generic_container->type_argc = count;
9888 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9890 klass->is_generic = 1;
9892 for (i = 0; i < count; i++) {
9893 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9894 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9895 klass->generic_container->type_params [i] = *param;
9896 /*Make sure we are a diferent type instance */
9897 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9898 klass->generic_container->type_params [i].info.pklass = NULL;
9899 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9901 g_assert (klass->generic_container->type_params [i].param.owner);
9904 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9908 * mono_reflection_create_internal_class:
9909 * @tb: a TypeBuilder object
9911 * Actually create the MonoClass that is associated with the TypeBuilder.
9914 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9918 MONO_ARCH_SAVE_REGS;
9920 klass = mono_class_from_mono_type (tb->type.type);
9922 mono_loader_lock ();
9923 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9924 MonoReflectionFieldBuilder *fb;
9926 MonoType *enum_basetype;
9928 g_assert (tb->fields != NULL);
9929 g_assert (mono_array_length (tb->fields) >= 1);
9931 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9933 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9934 mono_loader_unlock ();
9938 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9939 klass->element_class = mono_class_from_mono_type (enum_basetype);
9940 if (!klass->element_class)
9941 klass->element_class = mono_class_from_mono_type (enum_basetype);
9944 * get the element_class from the current corlib.
9946 ec = default_class_from_mono_type (enum_basetype);
9947 klass->instance_size = ec->instance_size;
9948 klass->size_inited = 1;
9950 * this is almost safe to do with enums and it's needed to be able
9951 * to create objects of the enum type (for use in SetConstant).
9953 /* FIXME: Does this mean enums can't have method overrides ? */
9954 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9956 mono_loader_unlock ();
9959 static MonoMarshalSpec*
9960 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9961 MonoReflectionMarshal *minfo)
9963 MonoMarshalSpec *res;
9965 res = image_g_new0 (image, MonoMarshalSpec, 1);
9966 res->native = minfo->type;
9968 switch (minfo->type) {
9969 case MONO_NATIVE_LPARRAY:
9970 res->data.array_data.elem_type = minfo->eltype;
9971 if (minfo->has_size) {
9972 res->data.array_data.param_num = minfo->param_num;
9973 res->data.array_data.num_elem = minfo->count;
9974 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9977 res->data.array_data.param_num = -1;
9978 res->data.array_data.num_elem = -1;
9979 res->data.array_data.elem_mult = -1;
9983 case MONO_NATIVE_BYVALTSTR:
9984 case MONO_NATIVE_BYVALARRAY:
9985 res->data.array_data.num_elem = minfo->count;
9988 case MONO_NATIVE_CUSTOM:
9989 if (minfo->marshaltyperef)
9990 res->data.custom_data.custom_name =
9991 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9993 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10002 #endif /* !DISABLE_REFLECTION_EMIT */
10004 MonoReflectionMarshalAsAttribute*
10005 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10006 MonoMarshalSpec *spec)
10008 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10009 MonoReflectionMarshalAsAttribute *minfo;
10012 if (!System_Reflection_Emit_MarshalAsAttribute) {
10013 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10014 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10015 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10018 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10019 minfo->utype = spec->native;
10021 switch (minfo->utype) {
10022 case MONO_NATIVE_LPARRAY:
10023 minfo->array_subtype = spec->data.array_data.elem_type;
10024 minfo->size_const = spec->data.array_data.num_elem;
10025 if (spec->data.array_data.param_num != -1)
10026 minfo->size_param_index = spec->data.array_data.param_num;
10029 case MONO_NATIVE_BYVALTSTR:
10030 case MONO_NATIVE_BYVALARRAY:
10031 minfo->size_const = spec->data.array_data.num_elem;
10034 case MONO_NATIVE_CUSTOM:
10035 if (spec->data.custom_data.custom_name) {
10036 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10038 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10040 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10042 if (spec->data.custom_data.cookie)
10043 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10053 #ifndef DISABLE_REFLECTION_EMIT
10055 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10056 ReflectionMethodBuilder *rmb,
10057 MonoMethodSignature *sig)
10061 MonoMethodWrapper *wrapperm;
10062 MonoMarshalSpec **specs;
10063 MonoReflectionMethodAux *method_aux;
10068 mono_error_init (&error);
10070 * Methods created using a MethodBuilder should have their memory allocated
10071 * inside the image mempool, while dynamic methods should have their memory
10074 dynamic = rmb->refs != NULL;
10075 image = dynamic ? NULL : klass->image;
10078 g_assert (!klass->generic_class);
10080 mono_loader_lock ();
10082 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10083 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10084 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10086 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10088 wrapperm = (MonoMethodWrapper*)m;
10090 m->dynamic = dynamic;
10092 m->flags = rmb->attrs;
10093 m->iflags = rmb->iattrs;
10094 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10096 m->signature = sig;
10097 m->sre_method = TRUE;
10098 m->skip_visibility = rmb->skip_visibility;
10099 if (rmb->table_idx)
10100 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10102 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10103 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10104 m->string_ctor = 1;
10106 m->signature->pinvoke = 1;
10107 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10108 m->signature->pinvoke = 1;
10110 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10112 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10113 g_assert (mono_error_ok (&error));
10114 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10115 g_assert (mono_error_ok (&error));
10117 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10119 if (klass->image->dynamic)
10120 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10122 mono_loader_unlock ();
10125 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10126 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10127 MonoMethodHeader *header;
10129 gint32 max_stack, i;
10130 gint32 num_locals = 0;
10131 gint32 num_clauses = 0;
10135 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10136 code_size = rmb->ilgen->code_len;
10137 max_stack = rmb->ilgen->max_stack;
10138 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10139 if (rmb->ilgen->ex_handlers)
10140 num_clauses = method_count_clauses (rmb->ilgen);
10143 code = mono_array_addr (rmb->code, guint8, 0);
10144 code_size = mono_array_length (rmb->code);
10145 /* we probably need to run a verifier on the code... */
10155 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10156 header->code_size = code_size;
10157 header->code = image_g_malloc (image, code_size);
10158 memcpy ((char*)header->code, code, code_size);
10159 header->max_stack = max_stack;
10160 header->init_locals = rmb->init_locals;
10161 header->num_locals = num_locals;
10163 for (i = 0; i < num_locals; ++i) {
10164 MonoReflectionLocalBuilder *lb =
10165 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10167 header->locals [i] = image_g_new0 (image, MonoType, 1);
10168 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10171 header->num_clauses = num_clauses;
10173 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10174 rmb->ilgen, num_clauses);
10177 wrapperm->header = header;
10180 if (rmb->generic_params) {
10181 int count = mono_array_length (rmb->generic_params);
10182 MonoGenericContainer *container = rmb->generic_container;
10184 g_assert (container);
10186 container->type_argc = count;
10187 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10188 container->owner.method = m;
10190 m->is_generic = TRUE;
10191 mono_method_set_generic_container (m, container);
10193 for (i = 0; i < count; i++) {
10194 MonoReflectionGenericParam *gp =
10195 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10196 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10197 container->type_params [i] = *param;
10201 * The method signature might have pointers to generic parameters that belong to other methods.
10202 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10203 * generic parameters.
10205 for (i = 0; i < m->signature->param_count; ++i) {
10206 MonoType *t = m->signature->params [i];
10207 if (t->type == MONO_TYPE_MVAR) {
10208 MonoGenericParam *gparam = t->data.generic_param;
10209 if (gparam->num < count) {
10210 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10211 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10217 if (klass->generic_container) {
10218 container->parent = klass->generic_container;
10219 container->context.class_inst = klass->generic_container->context.class_inst;
10221 container->context.method_inst = mono_get_shared_generic_inst (container);
10225 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10229 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10231 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10232 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10233 for (i = 0; i < rmb->nrefs; ++i)
10234 data [i + 1] = rmb->refs [i];
10239 /* Parameter info */
10242 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10243 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10244 for (i = 0; i <= m->signature->param_count; ++i) {
10245 MonoReflectionParamBuilder *pb;
10246 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10247 if ((i > 0) && (pb->attrs)) {
10248 /* Make a copy since it might point to a shared type structure */
10249 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10250 m->signature->params [i - 1]->attrs = pb->attrs;
10253 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10254 MonoDynamicImage *assembly;
10255 guint32 idx, def_type, len;
10259 if (!method_aux->param_defaults) {
10260 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10261 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10263 assembly = (MonoDynamicImage*)klass->image;
10264 idx = encode_constant (assembly, pb->def_value, &def_type);
10265 /* Copy the data from the blob since it might get realloc-ed */
10266 p = assembly->blob.data + idx;
10267 len = mono_metadata_decode_blob_size (p, &p2);
10269 method_aux->param_defaults [i] = image_g_malloc (image, len);
10270 method_aux->param_default_types [i] = def_type;
10271 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10275 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10276 g_assert (mono_error_ok (&error));
10279 if (!method_aux->param_cattr)
10280 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10281 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10287 /* Parameter marshalling */
10290 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10291 MonoReflectionParamBuilder *pb;
10292 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10293 if (pb->marshal_info) {
10295 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10296 specs [pb->position] =
10297 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10301 if (specs != NULL) {
10303 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10304 method_aux->param_marshall = specs;
10307 if (klass->image->dynamic && method_aux)
10308 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10310 mono_loader_unlock ();
10316 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10318 ReflectionMethodBuilder rmb;
10319 MonoMethodSignature *sig;
10321 mono_loader_lock ();
10322 sig = ctor_builder_to_signature (klass->image, mb);
10323 mono_loader_unlock ();
10325 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10327 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10328 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10330 /* If we are in a generic class, we might be called multiple times from inflate_method */
10331 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10332 /* ilgen is no longer needed */
10336 return mb->mhandle;
10340 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10342 ReflectionMethodBuilder rmb;
10343 MonoMethodSignature *sig;
10345 mono_loader_lock ();
10346 sig = method_builder_to_signature (klass->image, mb);
10347 mono_loader_unlock ();
10349 reflection_methodbuilder_from_method_builder (&rmb, mb);
10351 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10352 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10354 /* If we are in a generic class, we might be called multiple times from inflate_method */
10355 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10356 /* ilgen is no longer needed */
10359 return mb->mhandle;
10362 static MonoClassField*
10363 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10365 MonoClassField *field;
10369 field = g_new0 (MonoClassField, 1);
10371 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10372 g_assert (mono_error_ok (&error));
10373 if (fb->attrs || fb->modreq || fb->modopt) {
10374 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10375 field->type->attrs = fb->attrs;
10377 g_assert (klass->image->dynamic);
10378 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10379 g_free (field->type);
10380 field->type = mono_metadata_type_dup (klass->image, custom);
10383 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10385 if (fb->offset != -1)
10386 field->offset = fb->offset;
10387 field->parent = klass;
10388 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10390 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10397 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10400 MonoReflectionTypeBuilder *tb = NULL;
10401 gboolean is_dynamic = FALSE;
10402 MonoDomain *domain;
10403 MonoClass *geninst;
10405 mono_loader_lock ();
10407 domain = mono_object_domain (type);
10409 if (is_sre_type_builder (mono_object_class (type))) {
10410 tb = (MonoReflectionTypeBuilder *) type;
10413 } else if (is_sre_generic_instance (mono_object_class (type))) {
10414 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10415 MonoReflectionType *gtd = rgi->generic_type;
10417 if (is_sre_type_builder (mono_object_class (gtd))) {
10418 tb = (MonoReflectionTypeBuilder *)gtd;
10423 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10424 if (tb && tb->generic_container)
10425 mono_reflection_create_generic_class (tb);
10427 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10428 if (!klass->generic_container) {
10429 mono_loader_unlock ();
10433 if (klass->wastypebuilder) {
10434 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10439 mono_loader_unlock ();
10441 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10443 return &geninst->byval_arg;
10447 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10449 MonoGenericClass *gclass;
10450 MonoGenericInst *inst;
10452 g_assert (klass->generic_container);
10454 inst = mono_metadata_get_generic_inst (type_argc, types);
10455 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10457 return mono_generic_class_get_class (gclass);
10460 MonoReflectionMethod*
10461 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10464 MonoMethod *method, *inflated;
10465 MonoMethodInflated *imethod;
10466 MonoGenericContext tmp_context;
10467 MonoGenericInst *ginst;
10468 MonoType **type_argv;
10471 MONO_ARCH_SAVE_REGS;
10473 /*FIXME but this no longer should happen*/
10474 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10475 #ifndef DISABLE_REFLECTION_EMIT
10476 MonoReflectionMethodBuilder *mb = NULL;
10477 MonoReflectionTypeBuilder *tb;
10480 mb = (MonoReflectionMethodBuilder *) rmethod;
10481 tb = (MonoReflectionTypeBuilder *) mb->type;
10482 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10484 method = methodbuilder_to_mono_method (klass, mb);
10486 g_assert_not_reached ();
10490 method = rmethod->method;
10493 klass = method->klass;
10495 if (method->is_inflated)
10496 method = ((MonoMethodInflated *) method)->declaring;
10498 count = mono_method_signature (method)->generic_param_count;
10499 if (count != mono_array_length (types))
10502 type_argv = g_new0 (MonoType *, count);
10503 for (i = 0; i < count; i++) {
10504 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10505 type_argv [i] = mono_reflection_type_get_handle (garg);
10507 ginst = mono_metadata_get_generic_inst (count, type_argv);
10508 g_free (type_argv);
10510 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10511 tmp_context.method_inst = ginst;
10513 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10514 imethod = (MonoMethodInflated *) inflated;
10516 /*FIXME but I think this is no longer necessary*/
10517 if (method->klass->image->dynamic) {
10518 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10520 * This table maps metadata structures representing inflated methods/fields
10521 * to the reflection objects representing their generic definitions.
10523 mono_loader_lock ();
10524 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10525 mono_loader_unlock ();
10528 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10529 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10531 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10534 #ifndef DISABLE_REFLECTION_EMIT
10536 static MonoMethod *
10537 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10539 MonoMethodInflated *imethod;
10540 MonoGenericContext *context;
10544 * With generic code sharing the klass might not be inflated.
10545 * This can happen because classes inflated with their own
10546 * type arguments are "normalized" to the uninflated class.
10548 if (!klass->generic_class)
10551 context = mono_class_get_context (klass);
10553 if (klass->method.count && klass->methods) {
10554 /* Find the already created inflated method */
10555 for (i = 0; i < klass->method.count; ++i) {
10556 g_assert (klass->methods [i]->is_inflated);
10557 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10560 g_assert (i < klass->method.count);
10561 imethod = (MonoMethodInflated*)klass->methods [i];
10563 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10566 if (method->is_generic && method->klass->image->dynamic) {
10567 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10569 mono_loader_lock ();
10570 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10571 mono_loader_unlock ();
10573 return (MonoMethod *) imethod;
10576 static MonoMethod *
10577 inflate_method (MonoReflectionType *type, MonoObject *obj)
10579 MonoMethod *method;
10582 MonoClass *type_class = mono_object_class (type);
10584 if (is_sre_generic_instance (type_class)) {
10585 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10586 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10587 } else if (is_sre_type_builder (type_class)) {
10588 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10589 } else if (type->type) {
10590 gklass = mono_class_from_mono_type (type->type);
10591 gklass = mono_class_get_generic_type_definition (gklass);
10593 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10596 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10597 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10598 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10600 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10601 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10602 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10603 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10604 method = ((MonoReflectionMethod *) obj)->method;
10606 method = NULL; /* prevent compiler warning */
10607 g_error ("can't handle type %s", obj->vtable->klass->name);
10610 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10613 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10615 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10617 MonoGenericClass *gclass;
10618 MonoDynamicGenericClass *dgclass;
10619 MonoClass *klass, *gklass;
10623 MONO_ARCH_SAVE_REGS;
10625 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10626 klass = mono_class_from_mono_type (gtype);
10627 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10628 gclass = gtype->data.generic_class;
10630 if (!gclass->is_dynamic)
10633 dgclass = (MonoDynamicGenericClass *) gclass;
10635 if (dgclass->initialized)
10638 gklass = gclass->container_class;
10639 mono_class_init (gklass);
10641 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10643 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10644 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10645 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10647 for (i = 0; i < dgclass->count_fields; i++) {
10648 MonoObject *obj = mono_array_get (fields, gpointer, i);
10649 MonoClassField *field, *inflated_field = NULL;
10651 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10652 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10653 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10654 field = ((MonoReflectionField *) obj)->field;
10656 field = NULL; /* prevent compiler warning */
10657 g_assert_not_reached ();
10660 dgclass->fields [i] = *field;
10661 dgclass->fields [i].parent = klass;
10662 dgclass->fields [i].type = mono_class_inflate_generic_type (
10663 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10664 dgclass->field_generic_types [i] = field->type;
10665 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10666 dgclass->field_objects [i] = obj;
10668 if (inflated_field) {
10669 g_free (inflated_field);
10671 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10675 dgclass->initialized = TRUE;
10679 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10681 MonoDynamicGenericClass *dgclass;
10684 g_assert (gclass->is_dynamic);
10686 dgclass = (MonoDynamicGenericClass *)gclass;
10688 for (i = 0; i < dgclass->count_fields; ++i) {
10689 MonoClassField *field = dgclass->fields + i;
10690 mono_metadata_free_type (field->type);
10691 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10696 fix_partial_generic_class (MonoClass *klass)
10698 MonoClass *gklass = klass->generic_class->container_class;
10699 MonoDynamicGenericClass *dgclass;
10702 if (klass->wastypebuilder)
10705 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10706 if (klass->parent != gklass->parent) {
10708 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10709 if (mono_error_ok (&error)) {
10710 MonoClass *parent = mono_class_from_mono_type (parent_type);
10711 mono_metadata_free_type (parent_type);
10712 if (parent != klass->parent) {
10713 /*fool mono_class_setup_parent*/
10714 klass->supertypes = NULL;
10715 mono_class_setup_parent (klass, parent);
10718 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10719 mono_error_cleanup (&error);
10720 if (gklass->wastypebuilder)
10721 klass->wastypebuilder = TRUE;
10726 if (!dgclass->initialized)
10729 if (klass->method.count != gklass->method.count) {
10730 klass->method.count = gklass->method.count;
10731 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10733 for (i = 0; i < klass->method.count; i++) {
10734 klass->methods [i] = mono_class_inflate_generic_method_full (
10735 gklass->methods [i], klass, mono_class_get_context (klass));
10739 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10740 klass->interface_count = gklass->interface_count;
10741 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10742 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10744 for (i = 0; i < gklass->interface_count; ++i) {
10745 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10746 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10747 mono_metadata_free_type (iface_type);
10749 ensure_runtime_vtable (klass->interfaces [i]);
10751 klass->interfaces_inited = 1;
10754 if (klass->field.count != gklass->field.count) {
10755 klass->field.count = gklass->field.count;
10756 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10758 for (i = 0; i < klass->field.count; i++) {
10759 klass->fields [i] = gklass->fields [i];
10760 klass->fields [i].parent = klass;
10761 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10765 /*We can only finish with this klass once it's parent has as well*/
10766 if (gklass->wastypebuilder)
10767 klass->wastypebuilder = TRUE;
10772 ensure_generic_class_runtime_vtable (MonoClass *klass)
10774 MonoClass *gklass = klass->generic_class->container_class;
10776 ensure_runtime_vtable (gklass);
10778 fix_partial_generic_class (klass);
10782 ensure_runtime_vtable (MonoClass *klass)
10784 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10787 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10790 ensure_runtime_vtable (klass->parent);
10793 num = tb->ctors? mono_array_length (tb->ctors): 0;
10794 num += tb->num_methods;
10795 klass->method.count = num;
10796 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10797 num = tb->ctors? mono_array_length (tb->ctors): 0;
10798 for (i = 0; i < num; ++i)
10799 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10800 num = tb->num_methods;
10802 for (i = 0; i < num; ++i)
10803 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10805 if (tb->interfaces) {
10806 klass->interface_count = mono_array_length (tb->interfaces);
10807 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10808 for (i = 0; i < klass->interface_count; ++i) {
10809 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10810 klass->interfaces [i] = mono_class_from_mono_type (iface);
10811 ensure_runtime_vtable (klass->interfaces [i]);
10813 klass->interfaces_inited = 1;
10815 } else if (klass->generic_class){
10816 ensure_generic_class_runtime_vtable (klass);
10819 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10821 for (i = 0; i < klass->method.count; ++i) {
10822 MonoMethod *im = klass->methods [i];
10823 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10824 im->slot = slot_num++;
10827 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10828 mono_class_setup_interface_offsets (klass);
10829 mono_class_setup_interface_id (klass);
10833 * The generic vtable is needed even if image->run is not set since some
10834 * runtime code like ves_icall_Type_GetMethodsByName depends on
10835 * method->slot being defined.
10839 * tb->methods could not be freed since it is used for determining
10840 * overrides during dynamic vtable construction.
10845 mono_reflection_method_get_handle (MonoObject *method)
10847 MonoClass *class = mono_object_class (method);
10848 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10849 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10850 return sr_method->method;
10852 if (is_sre_method_builder (class)) {
10853 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10854 return mb->mhandle;
10856 if (is_sre_method_on_tb_inst (class)) {
10857 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10858 MonoMethod *result;
10859 /*FIXME move this to a proper method and unify with resolve_object*/
10860 if (m->method_args) {
10861 result = mono_reflection_method_on_tb_inst_get_handle (m);
10863 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10864 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10865 MonoMethod *mono_method;
10867 if (is_sre_method_builder (mono_object_class (m->mb)))
10868 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10869 else if (is_sr_mono_method (mono_object_class (m->mb)))
10870 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10872 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)));
10874 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10879 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10884 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10886 MonoReflectionTypeBuilder *tb;
10888 MonoReflectionMethod *m;
10891 *num_overrides = 0;
10893 g_assert (klass->image->dynamic);
10895 if (!mono_class_get_ref_info (klass))
10898 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10900 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10904 for (i = 0; i < tb->num_methods; ++i) {
10905 MonoReflectionMethodBuilder *mb =
10906 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10907 if (mb->override_methods)
10908 onum += mono_array_length (mb->override_methods);
10913 *overrides = g_new0 (MonoMethod*, onum * 2);
10916 for (i = 0; i < tb->num_methods; ++i) {
10917 MonoReflectionMethodBuilder *mb =
10918 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10919 if (mb->override_methods) {
10920 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10921 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10923 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10924 (*overrides) [onum * 2 + 1] = mb->mhandle;
10926 g_assert (mb->mhandle);
10934 *num_overrides = onum;
10938 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10940 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10941 MonoReflectionFieldBuilder *fb;
10942 MonoClassField *field;
10943 MonoImage *image = klass->image;
10944 const char *p, *p2;
10946 guint32 len, idx, real_size = 0;
10948 klass->field.count = tb->num_fields;
10949 klass->field.first = 0;
10951 mono_error_init (error);
10953 if (tb->class_size) {
10954 if ((tb->packing_size & 0xfffffff0) != 0) {
10955 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10956 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10959 klass->packing_size = tb->packing_size;
10960 real_size = klass->instance_size + tb->class_size;
10963 if (!klass->field.count) {
10964 klass->instance_size = MAX (klass->instance_size, real_size);
10968 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10969 mono_class_alloc_ext (klass);
10970 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10972 This is, guess what, a hack.
10973 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10974 On the static path no field class is resolved, only types are built. This is the right thing to do
10976 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10978 klass->size_inited = 1;
10980 for (i = 0; i < klass->field.count; ++i) {
10981 MonoArray *rva_data;
10982 fb = mono_array_get (tb->fields, gpointer, i);
10983 field = &klass->fields [i];
10984 field->name = mono_string_to_utf8_image (image, fb->name, error);
10985 if (!mono_error_ok (error))
10988 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10989 field->type->attrs = fb->attrs;
10991 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10994 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
10995 char *base = mono_array_addr (rva_data, char, 0);
10996 size_t size = mono_array_length (rva_data);
10997 char *data = mono_image_alloc (klass->image, size);
10998 memcpy (data, base, size);
10999 klass->ext->field_def_values [i].data = data;
11001 if (fb->offset != -1)
11002 field->offset = fb->offset;
11003 field->parent = klass;
11004 fb->handle = field;
11005 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11007 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11008 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11010 if (fb->def_value) {
11011 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11012 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11013 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11014 /* Copy the data from the blob since it might get realloc-ed */
11015 p = assembly->blob.data + idx;
11016 len = mono_metadata_decode_blob_size (p, &p2);
11018 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11019 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11023 klass->instance_size = MAX (klass->instance_size, real_size);
11024 mono_class_layout_fields (klass);
11028 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11030 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11031 MonoReflectionPropertyBuilder *pb;
11032 MonoImage *image = klass->image;
11033 MonoProperty *properties;
11036 mono_error_init (error);
11039 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11041 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11042 klass->ext->property.first = 0;
11044 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11045 klass->ext->properties = properties;
11046 for (i = 0; i < klass->ext->property.count; ++i) {
11047 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11048 properties [i].parent = klass;
11049 properties [i].attrs = pb->attrs;
11050 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11051 if (!mono_error_ok (error))
11053 if (pb->get_method)
11054 properties [i].get = pb->get_method->mhandle;
11055 if (pb->set_method)
11056 properties [i].set = pb->set_method->mhandle;
11058 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11059 if (pb->def_value) {
11061 const char *p, *p2;
11062 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11063 if (!klass->ext->prop_def_values)
11064 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11065 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11066 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11067 /* Copy the data from the blob since it might get realloc-ed */
11068 p = assembly->blob.data + idx;
11069 len = mono_metadata_decode_blob_size (p, &p2);
11071 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11072 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11077 MonoReflectionEvent *
11078 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11080 MonoEvent *event = g_new0 (MonoEvent, 1);
11083 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11085 event->parent = klass;
11086 event->attrs = eb->attrs;
11087 event->name = mono_string_to_utf8 (eb->name);
11088 if (eb->add_method)
11089 event->add = eb->add_method->mhandle;
11090 if (eb->remove_method)
11091 event->remove = eb->remove_method->mhandle;
11092 if (eb->raise_method)
11093 event->raise = eb->raise_method->mhandle;
11095 #ifndef MONO_SMALL_CONFIG
11096 if (eb->other_methods) {
11098 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11099 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11100 MonoReflectionMethodBuilder *mb =
11101 mono_array_get (eb->other_methods,
11102 MonoReflectionMethodBuilder*, j);
11103 event->other [j] = mb->mhandle;
11108 return mono_event_get_object (mono_object_domain (tb), klass, event);
11112 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11114 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11115 MonoReflectionEventBuilder *eb;
11116 MonoImage *image = klass->image;
11120 mono_error_init (error);
11123 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11125 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11126 klass->ext->event.first = 0;
11128 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11129 klass->ext->events = events;
11130 for (i = 0; i < klass->ext->event.count; ++i) {
11131 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11132 events [i].parent = klass;
11133 events [i].attrs = eb->attrs;
11134 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11135 if (!mono_error_ok (error))
11137 if (eb->add_method)
11138 events [i].add = eb->add_method->mhandle;
11139 if (eb->remove_method)
11140 events [i].remove = eb->remove_method->mhandle;
11141 if (eb->raise_method)
11142 events [i].raise = eb->raise_method->mhandle;
11144 #ifndef MONO_SMALL_CONFIG
11145 if (eb->other_methods) {
11147 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11148 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11149 MonoReflectionMethodBuilder *mb =
11150 mono_array_get (eb->other_methods,
11151 MonoReflectionMethodBuilder*, j);
11152 events [i].other [j] = mb->mhandle;
11156 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11161 remove_instantiations_of_and_ensure_contents (gpointer key,
11163 gpointer user_data)
11165 MonoType *type = (MonoType*)key;
11166 MonoClass *klass = (MonoClass*)user_data;
11168 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11169 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11176 check_array_for_usertypes (MonoArray *arr)
11183 for (i = 0; i < mono_array_length (arr); ++i)
11184 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11187 MonoReflectionType*
11188 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11192 MonoDomain* domain;
11193 MonoReflectionType* res;
11196 MONO_ARCH_SAVE_REGS;
11198 domain = mono_object_domain (tb);
11199 klass = mono_class_from_mono_type (tb->type.type);
11202 * Check for user defined Type subclasses.
11204 RESOLVE_TYPE (tb->parent);
11205 check_array_for_usertypes (tb->interfaces);
11207 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11208 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11210 RESOLVE_TYPE (fb->type);
11211 check_array_for_usertypes (fb->modreq);
11212 check_array_for_usertypes (fb->modopt);
11213 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11214 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11219 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11220 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11222 RESOLVE_TYPE (mb->rtype);
11223 check_array_for_usertypes (mb->return_modreq);
11224 check_array_for_usertypes (mb->return_modopt);
11225 check_array_for_usertypes (mb->parameters);
11226 if (mb->param_modreq)
11227 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11228 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11229 if (mb->param_modopt)
11230 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11231 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11236 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11237 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11239 check_array_for_usertypes (mb->parameters);
11240 if (mb->param_modreq)
11241 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11242 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11243 if (mb->param_modopt)
11244 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11245 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11250 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11253 * we need to lock the domain because the lock will be taken inside
11254 * So, we need to keep the locking order correct.
11256 mono_loader_lock ();
11257 mono_domain_lock (domain);
11258 if (klass->wastypebuilder) {
11259 mono_domain_unlock (domain);
11260 mono_loader_unlock ();
11261 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11264 * Fields to set in klass:
11265 * the various flags: delegate/unicode/contextbound etc.
11267 klass->flags = tb->attrs;
11268 klass->has_cctor = 1;
11269 klass->has_finalize = 1;
11270 klass->has_finalize_inited = 1;
11272 /* fool mono_class_setup_parent */
11273 klass->supertypes = NULL;
11274 mono_class_setup_parent (klass, klass->parent);
11275 mono_class_setup_mono_type (klass);
11278 if (!((MonoDynamicImage*)klass->image)->run) {
11279 if (klass->generic_container) {
11280 /* FIXME: The code below can't handle generic classes */
11281 klass->wastypebuilder = TRUE;
11282 mono_loader_unlock ();
11283 mono_domain_unlock (domain);
11284 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11289 /* enums are done right away */
11290 if (!klass->enumtype)
11291 ensure_runtime_vtable (klass);
11293 if (tb->subtypes) {
11294 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11295 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11296 mono_class_alloc_ext (klass);
11297 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)));
11301 klass->nested_classes_inited = TRUE;
11303 /* fields and object layout */
11304 if (klass->parent) {
11305 if (!klass->parent->size_inited)
11306 mono_class_init (klass->parent);
11307 klass->instance_size = klass->parent->instance_size;
11308 klass->sizes.class_size = 0;
11309 klass->min_align = klass->parent->min_align;
11310 /* if the type has no fields we won't call the field_setup
11311 * routine which sets up klass->has_references.
11313 klass->has_references |= klass->parent->has_references;
11315 klass->instance_size = sizeof (MonoObject);
11316 klass->min_align = 1;
11319 /* FIXME: handle packing_size and instance_size */
11320 typebuilder_setup_fields (klass, &error);
11321 if (!mono_error_ok (&error))
11323 typebuilder_setup_properties (klass, &error);
11324 if (!mono_error_ok (&error))
11327 typebuilder_setup_events (klass, &error);
11328 if (!mono_error_ok (&error))
11331 klass->wastypebuilder = TRUE;
11334 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11335 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11336 * we want to return normal System.MonoType objects, so clear these out from the cache.
11338 * Together with this we must ensure the contents of all instances to match the created type.
11340 if (domain->type_hash && klass->generic_container)
11341 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11343 mono_domain_unlock (domain);
11344 mono_loader_unlock ();
11346 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11347 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11348 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11351 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11352 g_assert (res != (MonoReflectionType*)tb);
11357 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11358 klass->wastypebuilder = TRUE;
11359 mono_domain_unlock (domain);
11360 mono_loader_unlock ();
11361 mono_error_raise_exception (&error);
11366 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11368 MonoGenericParamFull *param;
11373 MONO_ARCH_SAVE_REGS;
11375 image = &gparam->tbuilder->module->dynamic_image->image;
11377 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11379 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11380 g_assert (mono_error_ok (&error));
11381 param->param.num = gparam->index;
11383 if (gparam->mbuilder) {
11384 if (!gparam->mbuilder->generic_container) {
11385 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11386 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11387 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11388 gparam->mbuilder->generic_container->is_method = TRUE;
11390 * Cannot set owner.method, since the MonoMethod is not created yet.
11391 * Set the image field instead, so type_in_image () works.
11393 gparam->mbuilder->generic_container->image = klass->image;
11395 param->param.owner = gparam->mbuilder->generic_container;
11396 } else if (gparam->tbuilder) {
11397 if (!gparam->tbuilder->generic_container) {
11398 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11399 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11400 gparam->tbuilder->generic_container->owner.klass = klass;
11402 param->param.owner = gparam->tbuilder->generic_container;
11405 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11407 gparam->type.type = &pklass->byval_arg;
11409 mono_class_set_ref_info (pklass, gparam);
11410 mono_image_lock (image);
11411 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11412 mono_image_unlock (image);
11416 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11418 MonoReflectionModuleBuilder *module = sig->module;
11419 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11420 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11425 check_array_for_usertypes (sig->arguments);
11427 sigbuffer_init (&buf, 32);
11429 sigbuffer_add_value (&buf, 0x07);
11430 sigbuffer_add_value (&buf, na);
11431 if (assembly != NULL){
11432 for (i = 0; i < na; ++i) {
11433 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11434 encode_reflection_type (assembly, type, &buf);
11438 buflen = buf.p - buf.buf;
11439 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11440 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11441 sigbuffer_free (&buf);
11447 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11449 MonoDynamicImage *assembly = sig->module->dynamic_image;
11450 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11455 check_array_for_usertypes (sig->arguments);
11457 sigbuffer_init (&buf, 32);
11459 sigbuffer_add_value (&buf, 0x06);
11460 for (i = 0; i < na; ++i) {
11461 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11462 encode_reflection_type (assembly, type, &buf);
11465 buflen = buf.p - buf.buf;
11466 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11467 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11468 sigbuffer_free (&buf);
11474 MonoMethod *handle;
11475 MonoDomain *domain;
11476 } DynamicMethodReleaseData;
11479 * The runtime automatically clean up those after finalization.
11481 static MonoReferenceQueue *dynamic_method_queue;
11484 free_dynamic_method (void *dynamic_method)
11486 DynamicMethodReleaseData *data = dynamic_method;
11488 mono_runtime_free_method (data->domain, data->handle);
11493 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11495 MonoReferenceQueue *queue;
11496 MonoMethod *handle;
11497 DynamicMethodReleaseData *release_data;
11498 ReflectionMethodBuilder rmb;
11499 MonoMethodSignature *sig;
11504 if (mono_runtime_is_shutting_down ())
11505 mono_raise_exception (mono_get_exception_invalid_operation (""));
11507 if (!(queue = dynamic_method_queue)) {
11508 mono_loader_lock ();
11509 if (!(queue = dynamic_method_queue))
11510 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11511 mono_loader_unlock ();
11514 sig = dynamic_method_to_signature (mb);
11516 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11519 * Resolve references.
11522 * Every second entry in the refs array is reserved for storing handle_class,
11523 * which is needed by the ldtoken implementation in the JIT.
11525 rmb.nrefs = mb->nrefs;
11526 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11527 for (i = 0; i < mb->nrefs; i += 2) {
11528 MonoClass *handle_class;
11530 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11532 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11533 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11535 * The referenced DynamicMethod should already be created by the managed
11536 * code, except in the case of circular references. In that case, we store
11537 * method in the refs array, and fix it up later when the referenced
11538 * DynamicMethod is created.
11540 if (method->mhandle) {
11541 ref = method->mhandle;
11543 /* FIXME: GC object stored in unmanaged memory */
11546 /* FIXME: GC object stored in unmanaged memory */
11547 method->referenced_by = g_slist_append (method->referenced_by, mb);
11549 handle_class = mono_defaults.methodhandle_class;
11551 MonoException *ex = NULL;
11552 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11554 ex = mono_get_exception_type_load (NULL, NULL);
11555 else if (mono_security_core_clr_enabled ())
11556 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11560 mono_raise_exception (ex);
11565 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11566 rmb.refs [i + 1] = handle_class;
11569 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11571 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11572 release_data = g_new (DynamicMethodReleaseData, 1);
11573 release_data->handle = handle;
11574 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11575 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11576 g_free (release_data);
11578 /* Fix up refs entries pointing at us */
11579 for (l = mb->referenced_by; l; l = l->next) {
11580 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11581 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11584 g_assert (method->mhandle);
11586 data = (gpointer*)wrapper->method_data;
11587 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11588 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11589 data [i + 1] = mb->mhandle;
11592 g_slist_free (mb->referenced_by);
11596 /* ilgen is no longer needed */
11600 #endif /* DISABLE_REFLECTION_EMIT */
11604 * mono_reflection_is_valid_dynamic_token:
11606 * Returns TRUE if token is valid.
11610 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11612 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11615 MonoMethodSignature *
11616 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11618 MonoMethodSignature *sig;
11619 g_assert (image->dynamic);
11621 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11625 return mono_method_signature (method);
11628 #ifndef DISABLE_REFLECTION_EMIT
11631 * mono_reflection_lookup_dynamic_token:
11633 * Finish the Builder object pointed to by TOKEN and return the corresponding
11634 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11635 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11638 * LOCKING: Take the loader lock
11641 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11643 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11647 mono_loader_lock ();
11648 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11649 mono_loader_unlock ();
11652 g_error ("Could not find required dynamic token 0x%08x", token);
11658 handle_class = &klass;
11659 return resolve_object (image, obj, handle_class, context);
11663 * ensure_complete_type:
11665 * Ensure that KLASS is completed if it is a dynamic type, or references
11669 ensure_complete_type (MonoClass *klass)
11671 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11672 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11674 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11676 // Asserting here could break a lot of code
11677 //g_assert (klass->wastypebuilder);
11680 if (klass->generic_class) {
11681 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11684 for (i = 0; i < inst->type_argc; ++i) {
11685 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11691 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11693 gpointer result = NULL;
11695 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11696 result = mono_string_intern ((MonoString*)obj);
11697 *handle_class = mono_defaults.string_class;
11699 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11700 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11701 MonoClass *mc = mono_class_from_mono_type (type);
11702 if (!mono_class_init (mc))
11703 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11706 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11707 result = mono_class_from_mono_type (inflated);
11708 mono_metadata_free_type (inflated);
11710 result = mono_class_from_mono_type (type);
11712 *handle_class = mono_defaults.typehandle_class;
11714 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11715 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11716 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11717 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11718 result = ((MonoReflectionMethod*)obj)->method;
11720 result = mono_class_inflate_generic_method (result, context);
11721 *handle_class = mono_defaults.methodhandle_class;
11723 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11724 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11725 result = mb->mhandle;
11727 /* Type is not yet created */
11728 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11730 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11733 * Hopefully this has been filled in by calling CreateType() on the
11737 * TODO: This won't work if the application finishes another
11738 * TypeBuilder instance instead of this one.
11740 result = mb->mhandle;
11743 result = mono_class_inflate_generic_method (result, context);
11744 *handle_class = mono_defaults.methodhandle_class;
11745 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11746 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11748 result = cb->mhandle;
11750 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11752 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11753 result = cb->mhandle;
11756 result = mono_class_inflate_generic_method (result, context);
11757 *handle_class = mono_defaults.methodhandle_class;
11758 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11759 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11761 ensure_complete_type (field->parent);
11763 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11764 MonoClass *class = mono_class_from_mono_type (inflated);
11765 MonoClassField *inflated_field;
11766 gpointer iter = NULL;
11767 mono_metadata_free_type (inflated);
11768 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11769 if (!strcmp (field->name, inflated_field->name))
11772 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11773 result = inflated_field;
11777 *handle_class = mono_defaults.fieldhandle_class;
11779 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11780 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11781 result = fb->handle;
11784 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11786 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11787 result = fb->handle;
11790 if (fb->handle && fb->handle->parent->generic_container) {
11791 MonoClass *klass = fb->handle->parent;
11792 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11793 MonoClass *inflated = mono_class_from_mono_type (type);
11795 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11797 mono_metadata_free_type (type);
11799 *handle_class = mono_defaults.fieldhandle_class;
11800 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11801 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11802 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11805 klass = type->data.klass;
11806 if (klass->wastypebuilder) {
11807 /* Already created */
11811 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11812 result = type->data.klass;
11815 *handle_class = mono_defaults.typehandle_class;
11816 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11817 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11818 MonoMethodSignature *sig;
11821 if (helper->arguments)
11822 nargs = mono_array_length (helper->arguments);
11826 sig = mono_metadata_signature_alloc (image, nargs);
11827 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11828 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11830 if (helper->unmanaged_call_conv) { /* unmanaged */
11831 sig->call_convention = helper->unmanaged_call_conv - 1;
11832 sig->pinvoke = TRUE;
11833 } else if (helper->call_conv & 0x02) {
11834 sig->call_convention = MONO_CALL_VARARG;
11836 sig->call_convention = MONO_CALL_DEFAULT;
11839 sig->param_count = nargs;
11840 /* TODO: Copy type ? */
11841 sig->ret = helper->return_type->type;
11842 for (i = 0; i < nargs; ++i)
11843 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11846 *handle_class = NULL;
11847 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11848 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11849 /* Already created by the managed code */
11850 g_assert (method->mhandle);
11851 result = method->mhandle;
11852 *handle_class = mono_defaults.methodhandle_class;
11853 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11854 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11855 type = mono_class_inflate_generic_type (type, context);
11856 result = mono_class_from_mono_type (type);
11857 *handle_class = mono_defaults.typehandle_class;
11859 mono_metadata_free_type (type);
11860 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11861 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11862 type = mono_class_inflate_generic_type (type, context);
11863 result = mono_class_from_mono_type (type);
11864 *handle_class = mono_defaults.typehandle_class;
11866 mono_metadata_free_type (type);
11867 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11868 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11869 MonoClass *inflated;
11871 MonoClassField *field;
11873 if (is_sre_field_builder (mono_object_class (f->fb)))
11874 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11875 else if (is_sr_mono_field (mono_object_class (f->fb)))
11876 field = ((MonoReflectionField*)f->fb)->field;
11878 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)));
11880 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11881 inflated = mono_class_from_mono_type (type);
11883 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11884 ensure_complete_type (field->parent);
11886 mono_metadata_free_type (type);
11887 *handle_class = mono_defaults.fieldhandle_class;
11888 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11889 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11890 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11891 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11892 MonoMethod *method;
11894 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11895 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11896 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11897 method = ((MonoReflectionMethod *)c->cb)->method;
11899 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)));
11901 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11902 *handle_class = mono_defaults.methodhandle_class;
11903 mono_metadata_free_type (type);
11904 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11905 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11906 if (m->method_args) {
11907 result = mono_reflection_method_on_tb_inst_get_handle (m);
11909 result = mono_class_inflate_generic_method (result, context);
11911 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11912 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11913 MonoMethod *method;
11915 if (is_sre_method_builder (mono_object_class (m->mb)))
11916 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11917 else if (is_sr_mono_method (mono_object_class (m->mb)))
11918 method = ((MonoReflectionMethod *)m->mb)->method;
11920 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)));
11922 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11923 mono_metadata_free_type (type);
11925 *handle_class = mono_defaults.methodhandle_class;
11926 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11927 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11930 MonoMethod *method;
11934 mtype = mono_reflection_type_get_handle (m->parent);
11935 klass = mono_class_from_mono_type (mtype);
11937 /* Find the method */
11939 name = mono_string_to_utf8 (m->name);
11941 while ((method = mono_class_get_methods (klass, &iter))) {
11942 if (!strcmp (method->name, name))
11949 // FIXME: Check parameters/return value etc. match
11952 *handle_class = mono_defaults.methodhandle_class;
11953 } else if (is_sre_array (mono_object_get_class(obj)) ||
11954 is_sre_byref (mono_object_get_class(obj)) ||
11955 is_sre_pointer (mono_object_get_class(obj))) {
11956 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11957 MonoType *type = mono_reflection_type_get_handle (ref_type);
11960 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11961 result = mono_class_from_mono_type (inflated);
11962 mono_metadata_free_type (inflated);
11964 result = mono_class_from_mono_type (type);
11966 *handle_class = mono_defaults.typehandle_class;
11968 g_print ("%s\n", obj->vtable->klass->name);
11969 g_assert_not_reached ();
11974 #else /* DISABLE_REFLECTION_EMIT */
11977 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11979 g_assert_not_reached ();
11984 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11986 g_assert_not_reached ();
11990 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11992 g_assert_not_reached ();
11996 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11998 g_assert_not_reached ();
12002 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12004 g_assert_not_reached ();
12008 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12010 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12014 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12016 g_assert_not_reached ();
12020 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12022 g_assert_not_reached ();
12025 MonoReflectionModule *
12026 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12028 g_assert_not_reached ();
12033 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12035 g_assert_not_reached ();
12040 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12042 g_assert_not_reached ();
12047 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12048 gboolean create_open_instance, gboolean register_token)
12050 g_assert_not_reached ();
12055 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12060 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12062 g_assert_not_reached ();
12066 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12069 *num_overrides = 0;
12072 MonoReflectionEvent *
12073 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12075 g_assert_not_reached ();
12079 MonoReflectionType*
12080 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12082 g_assert_not_reached ();
12087 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12089 g_assert_not_reached ();
12093 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12095 g_assert_not_reached ();
12100 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12102 g_assert_not_reached ();
12107 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12112 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12118 mono_reflection_type_get_handle (MonoReflectionType* ref)
12126 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12128 g_assert_not_reached ();
12131 #endif /* DISABLE_REFLECTION_EMIT */
12133 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12134 const static guint32 declsec_flags_map[] = {
12135 0x00000000, /* empty */
12136 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12137 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12138 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12139 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12140 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12141 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12142 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12143 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12144 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12145 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12146 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12147 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12148 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12149 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12150 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12151 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12152 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12153 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12157 * Returns flags that includes all available security action associated to the handle.
12158 * @token: metadata token (either for a class or a method)
12159 * @image: image where resides the metadata.
12162 mono_declsec_get_flags (MonoImage *image, guint32 token)
12164 int index = mono_metadata_declsec_from_index (image, token);
12165 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12166 guint32 result = 0;
12170 /* HasSecurity can be present for other, not specially encoded, attributes,
12171 e.g. SuppressUnmanagedCodeSecurityAttribute */
12175 for (i = index; i < t->rows; i++) {
12176 guint32 cols [MONO_DECL_SECURITY_SIZE];
12178 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12179 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12182 action = cols [MONO_DECL_SECURITY_ACTION];
12183 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12184 result |= declsec_flags_map [action];
12186 g_assert_not_reached ();
12193 * Get the security actions (in the form of flags) associated with the specified method.
12195 * @method: The method for which we want the declarative security flags.
12196 * Return the declarative security flags for the method (only).
12198 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12199 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12202 mono_declsec_flags_from_method (MonoMethod *method)
12204 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12205 /* FIXME: No cache (for the moment) */
12206 guint32 idx = mono_method_get_index (method);
12207 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12208 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12209 return mono_declsec_get_flags (method->klass->image, idx);
12215 * Get the security actions (in the form of flags) associated with the specified class.
12217 * @klass: The class for which we want the declarative security flags.
12218 * Return the declarative security flags for the class.
12220 * Note: We cache the flags inside the MonoClass structure as this will get
12221 * called very often (at least for each method).
12224 mono_declsec_flags_from_class (MonoClass *klass)
12226 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12227 if (!klass->ext || !klass->ext->declsec_flags) {
12230 idx = mono_metadata_token_index (klass->type_token);
12231 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12232 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12233 mono_loader_lock ();
12234 mono_class_alloc_ext (klass);
12235 mono_loader_unlock ();
12236 /* we cache the flags on classes */
12237 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12239 return klass->ext->declsec_flags;
12245 * Get the security actions (in the form of flags) associated with the specified assembly.
12247 * @assembly: The assembly for which we want the declarative security flags.
12248 * Return the declarative security flags for the assembly.
12251 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12253 guint32 idx = 1; /* there is only one assembly */
12254 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12255 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12256 return mono_declsec_get_flags (assembly->image, idx);
12261 * Fill actions for the specific index (which may either be an encoded class token or
12262 * an encoded method token) from the metadata image.
12263 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12266 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12267 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12269 MonoBoolean result = FALSE;
12271 guint32 cols [MONO_DECL_SECURITY_SIZE];
12272 int index = mono_metadata_declsec_from_index (image, token);
12275 t = &image->tables [MONO_TABLE_DECLSECURITY];
12276 for (i = index; i < t->rows; i++) {
12277 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12279 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12282 /* if present only replace (class) permissions with method permissions */
12283 /* if empty accept either class or method permissions */
12284 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12285 if (!actions->demand.blob) {
12286 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12287 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12288 actions->demand.blob = (char*) (blob + 2);
12289 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12292 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12293 if (!actions->noncasdemand.blob) {
12294 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12295 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12296 actions->noncasdemand.blob = (char*) (blob + 2);
12297 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12300 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12301 if (!actions->demandchoice.blob) {
12302 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12303 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12304 actions->demandchoice.blob = (char*) (blob + 2);
12305 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12315 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12316 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12318 guint32 idx = mono_metadata_token_index (klass->type_token);
12319 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12320 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12321 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12325 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12326 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12328 guint32 idx = mono_method_get_index (method);
12329 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12330 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12331 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12335 * Collect all actions (that requires to generate code in mini) assigned for
12336 * the specified method.
12337 * Note: Don't use the content of actions if the function return FALSE.
12340 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12342 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12343 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12344 MonoBoolean result = FALSE;
12347 /* quick exit if no declarative security is present in the metadata */
12348 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12351 /* we want the original as the wrapper is "free" of the security informations */
12352 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12353 method = mono_marshal_method_from_wrapper (method);
12358 /* First we look for method-level attributes */
12359 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12360 mono_class_init (method->klass);
12361 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12363 result = mono_declsec_get_method_demands_params (method, demands,
12364 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12367 /* Here we use (or create) the class declarative cache to look for demands */
12368 flags = mono_declsec_flags_from_class (method->klass);
12369 if (flags & mask) {
12371 mono_class_init (method->klass);
12372 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12374 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12375 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12378 /* The boolean return value is used as a shortcut in case nothing needs to
12379 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12385 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12387 * Note: Don't use the content of actions if the function return FALSE.
12390 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12392 MonoBoolean result = FALSE;
12395 /* quick exit if no declarative security is present in the metadata */
12396 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12399 /* we want the original as the wrapper is "free" of the security informations */
12400 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12401 method = mono_marshal_method_from_wrapper (method);
12406 /* results are independant - zeroize both */
12407 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12408 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12410 /* First we look for method-level attributes */
12411 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12412 mono_class_init (method->klass);
12414 result = mono_declsec_get_method_demands_params (method, cmethod,
12415 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12418 /* Here we use (or create) the class declarative cache to look for demands */
12419 flags = mono_declsec_flags_from_class (method->klass);
12420 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12421 mono_class_init (method->klass);
12423 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12424 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12431 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12433 * @klass The inherited class - this is the class that provides the security check (attributes)
12435 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12437 * Note: Don't use the content of actions if the function return FALSE.
12440 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12442 MonoBoolean result = FALSE;
12445 /* quick exit if no declarative security is present in the metadata */
12446 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12449 /* Here we use (or create) the class declarative cache to look for demands */
12450 flags = mono_declsec_flags_from_class (klass);
12451 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12452 mono_class_init (klass);
12453 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12455 result |= mono_declsec_get_class_demands_params (klass, demands,
12456 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12463 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12465 * Note: Don't use the content of actions if the function return FALSE.
12468 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12470 /* quick exit if no declarative security is present in the metadata */
12471 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12474 /* we want the original as the wrapper is "free" of the security informations */
12475 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12476 method = mono_marshal_method_from_wrapper (method);
12481 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12482 mono_class_init (method->klass);
12483 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12485 return mono_declsec_get_method_demands_params (method, demands,
12486 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12493 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12495 guint32 cols [MONO_DECL_SECURITY_SIZE];
12499 int index = mono_metadata_declsec_from_index (image, token);
12503 t = &image->tables [MONO_TABLE_DECLSECURITY];
12504 for (i = index; i < t->rows; i++) {
12505 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12507 /* shortcut - index are ordered */
12508 if (token != cols [MONO_DECL_SECURITY_PARENT])
12511 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12512 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12513 entry->blob = (char*) (metadata + 2);
12514 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12523 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12525 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12526 guint32 idx = mono_method_get_index (method);
12527 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12528 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12529 return get_declsec_action (method->klass->image, idx, action, entry);
12535 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12538 guint32 flags = mono_declsec_flags_from_class (klass);
12539 if (declsec_flags_map [action] & flags) {
12540 guint32 idx = mono_metadata_token_index (klass->type_token);
12541 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12542 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12543 return get_declsec_action (klass->image, idx, action, entry);
12549 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12551 guint32 idx = 1; /* there is only one assembly */
12552 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12553 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12555 return get_declsec_action (assembly->image, idx, action, entry);
12559 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12561 MonoObject *res, *exc;
12563 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12564 static MonoMethod *method = NULL;
12566 if (!System_Reflection_Emit_TypeBuilder) {
12567 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12568 g_assert (System_Reflection_Emit_TypeBuilder);
12570 if (method == NULL) {
12571 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12576 * The result of mono_type_get_object () might be a System.MonoType but we
12577 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12579 g_assert (mono_class_get_ref_info (klass));
12580 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12582 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12584 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12588 return *(MonoBoolean*)mono_object_unbox (res);
12592 * mono_reflection_type_get_type:
12593 * @reftype: the System.Type object
12595 * Returns the MonoType* associated with the C# System.Type object @reftype.
12598 mono_reflection_type_get_type (MonoReflectionType *reftype)
12600 g_assert (reftype);
12602 return mono_reflection_type_get_handle (reftype);