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 case MONO_TABLE_MEMBERREF:
1295 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1298 g_warning ("got wrong token in custom attr");
1301 values [MONO_CUSTOM_ATTR_TYPE] = type;
1303 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1304 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1305 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1306 values += MONO_CUSTOM_ATTR_SIZE;
1312 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1314 MonoDynamicTable *table;
1316 guint32 count, i, idx;
1317 MonoReflectionPermissionSet *perm;
1322 count = mono_array_length (permissions);
1323 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1324 table->rows += count;
1325 alloc_table (table, table->rows);
1327 for (i = 0; i < mono_array_length (permissions); ++i) {
1328 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1330 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1332 idx = mono_metadata_token_index (parent_token);
1333 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1334 switch (mono_metadata_token_table (parent_token)) {
1335 case MONO_TABLE_TYPEDEF:
1336 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1338 case MONO_TABLE_METHOD:
1339 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1341 case MONO_TABLE_ASSEMBLY:
1342 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1345 g_assert_not_reached ();
1348 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1349 values [MONO_DECL_SECURITY_PARENT] = idx;
1350 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1357 * Fill in the MethodDef and ParamDef tables for a method.
1358 * This is used for both normal methods and constructors.
1361 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1363 MonoDynamicTable *table;
1367 /* room in this table is already allocated */
1368 table = &assembly->tables [MONO_TABLE_METHOD];
1369 *mb->table_idx = table->next_idx ++;
1370 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1371 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1372 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1373 values [MONO_METHOD_FLAGS] = mb->attrs;
1374 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1375 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1376 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1378 table = &assembly->tables [MONO_TABLE_PARAM];
1379 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1381 mono_image_add_decl_security (assembly,
1382 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1385 MonoDynamicTable *mtable;
1388 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1389 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1392 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1393 if (mono_array_get (mb->pinfo, gpointer, i))
1396 table->rows += count;
1397 alloc_table (table, table->rows);
1398 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1399 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1400 MonoReflectionParamBuilder *pb;
1401 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1402 values [MONO_PARAM_FLAGS] = pb->attrs;
1403 values [MONO_PARAM_SEQUENCE] = i;
1404 if (pb->name != NULL) {
1405 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1407 values [MONO_PARAM_NAME] = 0;
1409 values += MONO_PARAM_SIZE;
1410 if (pb->marshal_info) {
1412 alloc_table (mtable, mtable->rows);
1413 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1414 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1415 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1417 pb->table_idx = table->next_idx++;
1418 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1419 guint32 field_type = 0;
1420 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1422 alloc_table (mtable, mtable->rows);
1423 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1424 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1425 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1426 mvalues [MONO_CONSTANT_TYPE] = field_type;
1427 mvalues [MONO_CONSTANT_PADDING] = 0;
1434 #ifndef DISABLE_REFLECTION_EMIT
1436 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1438 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1440 rmb->ilgen = mb->ilgen;
1441 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1442 rmb->parameters = mb->parameters;
1443 rmb->generic_params = mb->generic_params;
1444 rmb->generic_container = mb->generic_container;
1445 rmb->opt_types = NULL;
1446 rmb->pinfo = mb->pinfo;
1447 rmb->attrs = mb->attrs;
1448 rmb->iattrs = mb->iattrs;
1449 rmb->call_conv = mb->call_conv;
1450 rmb->code = mb->code;
1451 rmb->type = mb->type;
1452 rmb->name = mb->name;
1453 rmb->table_idx = &mb->table_idx;
1454 rmb->init_locals = mb->init_locals;
1455 rmb->skip_visibility = FALSE;
1456 rmb->return_modreq = mb->return_modreq;
1457 rmb->return_modopt = mb->return_modopt;
1458 rmb->param_modreq = mb->param_modreq;
1459 rmb->param_modopt = mb->param_modopt;
1460 rmb->permissions = mb->permissions;
1461 rmb->mhandle = mb->mhandle;
1466 rmb->charset = mb->charset;
1467 rmb->extra_flags = mb->extra_flags;
1468 rmb->native_cc = mb->native_cc;
1469 rmb->dllentry = mb->dllentry;
1475 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1477 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1479 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1481 rmb->ilgen = mb->ilgen;
1482 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1483 rmb->parameters = mb->parameters;
1484 rmb->generic_params = NULL;
1485 rmb->generic_container = NULL;
1486 rmb->opt_types = NULL;
1487 rmb->pinfo = mb->pinfo;
1488 rmb->attrs = mb->attrs;
1489 rmb->iattrs = mb->iattrs;
1490 rmb->call_conv = mb->call_conv;
1492 rmb->type = mb->type;
1493 rmb->name = mono_string_new (mono_domain_get (), name);
1494 rmb->table_idx = &mb->table_idx;
1495 rmb->init_locals = mb->init_locals;
1496 rmb->skip_visibility = FALSE;
1497 rmb->return_modreq = NULL;
1498 rmb->return_modopt = NULL;
1499 rmb->param_modreq = mb->param_modreq;
1500 rmb->param_modopt = mb->param_modopt;
1501 rmb->permissions = mb->permissions;
1502 rmb->mhandle = mb->mhandle;
1508 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1510 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1512 rmb->ilgen = mb->ilgen;
1513 rmb->rtype = mb->rtype;
1514 rmb->parameters = mb->parameters;
1515 rmb->generic_params = NULL;
1516 rmb->generic_container = NULL;
1517 rmb->opt_types = NULL;
1519 rmb->attrs = mb->attrs;
1521 rmb->call_conv = mb->call_conv;
1523 rmb->type = (MonoObject *) mb->owner;
1524 rmb->name = mb->name;
1525 rmb->table_idx = NULL;
1526 rmb->init_locals = mb->init_locals;
1527 rmb->skip_visibility = mb->skip_visibility;
1528 rmb->return_modreq = NULL;
1529 rmb->return_modopt = NULL;
1530 rmb->param_modreq = NULL;
1531 rmb->param_modopt = NULL;
1532 rmb->permissions = NULL;
1533 rmb->mhandle = mb->mhandle;
1540 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1542 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1543 MonoDynamicTable *table;
1546 MonoReflectionMethod *m;
1549 if (!mb->override_methods)
1552 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1553 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1555 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1557 alloc_table (table, table->rows);
1558 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1559 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1560 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1562 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1563 switch (mono_metadata_token_table (tok)) {
1564 case MONO_TABLE_MEMBERREF:
1565 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1567 case MONO_TABLE_METHOD:
1568 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1571 g_assert_not_reached ();
1573 values [MONO_METHODIMPL_DECLARATION] = tok;
1577 #ifndef DISABLE_REFLECTION_EMIT
1579 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1581 MonoDynamicTable *table;
1583 ReflectionMethodBuilder rmb;
1586 reflection_methodbuilder_from_method_builder (&rmb, mb);
1588 mono_image_basic_method (&rmb, assembly);
1589 mb->table_idx = *rmb.table_idx;
1591 if (mb->dll) { /* It's a P/Invoke method */
1593 /* map CharSet values to on-disk values */
1594 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1595 int extra_flags = mb->extra_flags;
1596 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1598 alloc_table (table, table->rows);
1599 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1601 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1602 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1604 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1606 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1607 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1608 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1609 table = &assembly->tables [MONO_TABLE_MODULEREF];
1611 alloc_table (table, table->rows);
1612 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1613 values [MONO_IMPLMAP_SCOPE] = table->rows;
1617 if (mb->generic_params) {
1618 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1619 table->rows += mono_array_length (mb->generic_params);
1620 alloc_table (table, table->rows);
1621 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1622 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1624 mono_image_get_generic_param_info (
1625 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1632 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1634 ReflectionMethodBuilder rmb;
1636 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1638 mono_image_basic_method (&rmb, assembly);
1639 mb->table_idx = *rmb.table_idx;
1644 type_get_fully_qualified_name (MonoType *type)
1646 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1650 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1654 klass = mono_class_from_mono_type (type);
1656 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1657 ta = klass->image->assembly;
1658 if (ta->dynamic || (ta == ass)) {
1659 if (klass->generic_class || klass->generic_container)
1660 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1661 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1663 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1666 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1669 #ifndef DISABLE_REFLECTION_EMIT
1670 /*field_image is the image to which the eventual custom mods have been encoded against*/
1672 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1675 guint32 idx, i, token;
1677 if (!assembly->save)
1680 sigbuffer_init (&buf, 32);
1682 sigbuffer_add_value (&buf, 0x06);
1683 /* encode custom attributes before the type */
1684 if (type->num_mods) {
1685 for (i = 0; i < type->num_mods; ++i) {
1687 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1689 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1691 token = type->modifiers [i].token;
1694 if (type->modifiers [i].required)
1695 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1699 sigbuffer_add_value (&buf, token);
1702 encode_type (assembly, type, &buf);
1703 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1704 sigbuffer_free (&buf);
1710 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1714 guint32 typespec = 0;
1718 init_type_builder_generics (fb->type);
1720 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1721 class = mono_class_from_mono_type (type);
1723 sigbuffer_init (&buf, 32);
1725 sigbuffer_add_value (&buf, 0x06);
1726 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1727 /* encode custom attributes before the type */
1729 if (class->generic_container)
1730 typespec = create_typespec (assembly, type);
1733 MonoGenericClass *gclass;
1734 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1735 encode_generic_class (assembly, gclass, &buf);
1737 encode_type (assembly, type, &buf);
1739 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1740 sigbuffer_free (&buf);
1745 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1746 char blob_size [64];
1747 char *b = blob_size;
1750 guint32 idx = 0, len = 0, dummy = 0;
1752 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1753 guint32 fpa_double [2];
1758 p = buf = g_malloc (64);
1760 *ret_type = MONO_TYPE_CLASS;
1762 box_val = (char*)&dummy;
1764 box_val = ((char*)val) + sizeof (MonoObject);
1765 *ret_type = val->vtable->klass->byval_arg.type;
1768 switch (*ret_type) {
1769 case MONO_TYPE_BOOLEAN:
1774 case MONO_TYPE_CHAR:
1791 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1792 fpa_p = (guint32*)box_val;
1793 fpa_double [0] = fpa_p [1];
1794 fpa_double [1] = fpa_p [0];
1795 box_val = (char*)fpa_double;
1799 case MONO_TYPE_VALUETYPE: {
1800 MonoClass *klass = val->vtable->klass;
1802 if (klass->enumtype) {
1803 *ret_type = mono_class_enum_basetype (klass)->type;
1805 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1808 g_error ("we can't encode valuetypes, we should have never reached this line");
1811 case MONO_TYPE_CLASS:
1813 case MONO_TYPE_STRING: {
1814 MonoString *str = (MonoString*)val;
1815 /* there is no signature */
1816 len = str->length * 2;
1817 mono_metadata_encode_value (len, b, &b);
1818 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1820 char *swapped = g_malloc (2 * mono_string_length (str));
1821 const char *p = (const char*)mono_string_chars (str);
1823 swap_with_size (swapped, p, 2, mono_string_length (str));
1824 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1834 case MONO_TYPE_GENERICINST:
1835 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1838 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1841 /* there is no signature */
1842 mono_metadata_encode_value (len, b, &b);
1843 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1844 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1845 swap_with_size (blob_size, box_val, len, 1);
1846 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1848 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1856 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1861 sigbuffer_init (&buf, 32);
1863 sigbuffer_add_value (&buf, minfo->type);
1865 switch (minfo->type) {
1866 case MONO_NATIVE_BYVALTSTR:
1867 case MONO_NATIVE_BYVALARRAY:
1868 sigbuffer_add_value (&buf, minfo->count);
1870 case MONO_NATIVE_LPARRAY:
1871 if (minfo->eltype || minfo->has_size) {
1872 sigbuffer_add_value (&buf, minfo->eltype);
1873 if (minfo->has_size) {
1874 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1875 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1877 /* LAMESPEC: ElemMult is undocumented */
1878 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1882 case MONO_NATIVE_SAFEARRAY:
1884 sigbuffer_add_value (&buf, minfo->eltype);
1886 case MONO_NATIVE_CUSTOM:
1888 str = mono_string_to_utf8 (minfo->guid);
1890 sigbuffer_add_value (&buf, len);
1891 sigbuffer_add_mem (&buf, str, len);
1894 sigbuffer_add_value (&buf, 0);
1896 /* native type name */
1897 sigbuffer_add_value (&buf, 0);
1898 /* custom marshaler type name */
1899 if (minfo->marshaltype || minfo->marshaltyperef) {
1900 if (minfo->marshaltyperef)
1901 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1903 str = mono_string_to_utf8 (minfo->marshaltype);
1905 sigbuffer_add_value (&buf, len);
1906 sigbuffer_add_mem (&buf, str, len);
1909 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1910 sigbuffer_add_value (&buf, 0);
1912 if (minfo->mcookie) {
1913 str = mono_string_to_utf8 (minfo->mcookie);
1915 sigbuffer_add_value (&buf, len);
1916 sigbuffer_add_mem (&buf, str, len);
1919 sigbuffer_add_value (&buf, 0);
1925 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1926 sigbuffer_free (&buf);
1931 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1933 MonoDynamicTable *table;
1936 /* maybe this fixup should be done in the C# code */
1937 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1938 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1939 table = &assembly->tables [MONO_TABLE_FIELD];
1940 fb->table_idx = table->next_idx ++;
1941 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1942 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1943 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1944 values [MONO_FIELD_FLAGS] = fb->attrs;
1945 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1947 if (fb->offset != -1) {
1948 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1950 alloc_table (table, table->rows);
1951 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1952 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1953 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1955 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1956 guint32 field_type = 0;
1957 table = &assembly->tables [MONO_TABLE_CONSTANT];
1959 alloc_table (table, table->rows);
1960 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1961 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1962 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1963 values [MONO_CONSTANT_TYPE] = field_type;
1964 values [MONO_CONSTANT_PADDING] = 0;
1966 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1968 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1970 alloc_table (table, table->rows);
1971 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1972 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1974 * We store it in the code section because it's simpler for now.
1977 if (mono_array_length (fb->rva_data) >= 10)
1978 stream_data_align (&assembly->code);
1979 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1981 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1982 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1984 if (fb->marshal_info) {
1985 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1987 alloc_table (table, table->rows);
1988 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1989 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1990 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1995 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1998 guint32 nparams = 0;
1999 MonoReflectionMethodBuilder *mb = fb->get_method;
2000 MonoReflectionMethodBuilder *smb = fb->set_method;
2003 if (mb && mb->parameters)
2004 nparams = mono_array_length (mb->parameters);
2005 if (!mb && smb && smb->parameters)
2006 nparams = mono_array_length (smb->parameters) - 1;
2007 sigbuffer_init (&buf, 32);
2008 if (fb->call_conv & 0x20)
2009 sigbuffer_add_byte (&buf, 0x28);
2011 sigbuffer_add_byte (&buf, 0x08);
2012 sigbuffer_add_value (&buf, nparams);
2014 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2015 for (i = 0; i < nparams; ++i) {
2016 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2017 encode_reflection_type (assembly, pt, &buf);
2019 } else if (smb && smb->parameters) {
2020 /* the property type is the last param */
2021 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2022 for (i = 0; i < nparams; ++i) {
2023 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2024 encode_reflection_type (assembly, pt, &buf);
2027 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2030 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2031 sigbuffer_free (&buf);
2036 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2038 MonoDynamicTable *table;
2040 guint num_methods = 0;
2044 * we need to set things in the following tables:
2045 * PROPERTYMAP (info already filled in _get_type_info ())
2046 * PROPERTY (rows already preallocated in _get_type_info ())
2047 * METHOD (method info already done with the generic method code)
2051 table = &assembly->tables [MONO_TABLE_PROPERTY];
2052 pb->table_idx = table->next_idx ++;
2053 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2054 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2055 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2056 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2058 /* FIXME: we still don't handle 'other' methods */
2059 if (pb->get_method) num_methods ++;
2060 if (pb->set_method) num_methods ++;
2062 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2063 table->rows += num_methods;
2064 alloc_table (table, table->rows);
2066 if (pb->get_method) {
2067 semaidx = table->next_idx ++;
2068 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2069 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2070 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2071 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2073 if (pb->set_method) {
2074 semaidx = table->next_idx ++;
2075 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2076 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2077 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2078 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2080 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2081 guint32 field_type = 0;
2082 table = &assembly->tables [MONO_TABLE_CONSTANT];
2084 alloc_table (table, table->rows);
2085 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2086 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2087 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2088 values [MONO_CONSTANT_TYPE] = field_type;
2089 values [MONO_CONSTANT_PADDING] = 0;
2094 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2096 MonoDynamicTable *table;
2098 guint num_methods = 0;
2102 * we need to set things in the following tables:
2103 * EVENTMAP (info already filled in _get_type_info ())
2104 * EVENT (rows already preallocated in _get_type_info ())
2105 * METHOD (method info already done with the generic method code)
2108 table = &assembly->tables [MONO_TABLE_EVENT];
2109 eb->table_idx = table->next_idx ++;
2110 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2111 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2112 values [MONO_EVENT_FLAGS] = eb->attrs;
2113 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2116 * FIXME: we still don't handle 'other' methods
2118 if (eb->add_method) num_methods ++;
2119 if (eb->remove_method) num_methods ++;
2120 if (eb->raise_method) num_methods ++;
2122 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2123 table->rows += num_methods;
2124 alloc_table (table, table->rows);
2126 if (eb->add_method) {
2127 semaidx = table->next_idx ++;
2128 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2129 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2130 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2131 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2133 if (eb->remove_method) {
2134 semaidx = table->next_idx ++;
2135 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2136 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2137 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2138 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2140 if (eb->raise_method) {
2141 semaidx = table->next_idx ++;
2142 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2143 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2144 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2145 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2150 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2152 MonoDynamicTable *table;
2153 guint32 num_constraints, i;
2157 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2158 num_constraints = gparam->iface_constraints ?
2159 mono_array_length (gparam->iface_constraints) : 0;
2160 table->rows += num_constraints;
2161 if (gparam->base_type)
2163 alloc_table (table, table->rows);
2165 if (gparam->base_type) {
2166 table_idx = table->next_idx ++;
2167 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2169 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2170 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2171 assembly, mono_reflection_type_get_handle (gparam->base_type));
2174 for (i = 0; i < num_constraints; i++) {
2175 MonoReflectionType *constraint = mono_array_get (
2176 gparam->iface_constraints, gpointer, i);
2178 table_idx = table->next_idx ++;
2179 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2181 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2182 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2183 assembly, mono_reflection_type_get_handle (constraint));
2188 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2190 GenericParamTableEntry *entry;
2193 * The GenericParam table must be sorted according to the `owner' field.
2194 * We need to do this sorting prior to writing the GenericParamConstraint
2195 * table, since we have to use the final GenericParam table indices there
2196 * and they must also be sorted.
2199 entry = g_new0 (GenericParamTableEntry, 1);
2200 entry->owner = owner;
2201 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2202 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2203 entry->gparam = gparam;
2205 g_ptr_array_add (assembly->gen_params, entry);
2209 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2211 MonoDynamicTable *table;
2212 MonoGenericParam *param;
2216 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2217 table_idx = table->next_idx ++;
2218 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2220 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2222 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2223 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2224 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2225 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2227 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2229 encode_constraints (entry->gparam, table_idx, assembly);
2233 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2235 MonoDynamicTable *table;
2238 guint32 cols [MONO_ASSEMBLY_SIZE];
2242 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2245 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2246 table = &assembly->tables [MONO_TABLE_MODULEREF];
2247 token = table->next_idx ++;
2249 alloc_table (table, table->rows);
2250 values = table->values + token * MONO_MODULEREF_SIZE;
2251 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2253 token <<= MONO_RESOLTION_SCOPE_BITS;
2254 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2255 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2260 if (image->assembly->dynamic)
2262 memset (cols, 0, sizeof (cols));
2264 /* image->assembly->image is the manifest module */
2265 image = image->assembly->image;
2266 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2269 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2270 token = table->next_idx ++;
2272 alloc_table (table, table->rows);
2273 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2274 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2275 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2276 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2277 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2278 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2279 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2280 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2281 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2283 if (strcmp ("", image->assembly->aname.culture)) {
2284 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2285 image->assembly->aname.culture);
2288 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2289 guchar pubtoken [9];
2291 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2292 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2294 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2296 token <<= MONO_RESOLTION_SCOPE_BITS;
2297 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2298 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2303 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2305 MonoDynamicTable *table;
2310 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2313 sigbuffer_init (&buf, 32);
2314 switch (type->type) {
2315 case MONO_TYPE_FNPTR:
2317 case MONO_TYPE_SZARRAY:
2318 case MONO_TYPE_ARRAY:
2320 case MONO_TYPE_MVAR:
2321 case MONO_TYPE_GENERICINST:
2322 encode_type (assembly, type, &buf);
2324 case MONO_TYPE_CLASS:
2325 case MONO_TYPE_VALUETYPE: {
2326 MonoClass *k = mono_class_from_mono_type (type);
2327 if (!k || !k->generic_container) {
2328 sigbuffer_free (&buf);
2331 encode_type (assembly, type, &buf);
2335 sigbuffer_free (&buf);
2339 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2340 if (assembly->save) {
2341 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2342 alloc_table (table, table->rows + 1);
2343 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2344 values [MONO_TYPESPEC_SIGNATURE] = token;
2346 sigbuffer_free (&buf);
2348 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2349 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2355 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2357 MonoDynamicTable *table;
2359 guint32 token, scope, enclosing;
2362 /* if the type requires a typespec, we must try that first*/
2363 if (try_typespec && (token = create_typespec (assembly, type)))
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2368 klass = mono_class_from_mono_type (type);
2370 klass = mono_class_from_mono_type (type);
2373 * If it's in the same module and not a generic type parameter:
2375 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2376 (type->type != MONO_TYPE_MVAR)) {
2377 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2378 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2379 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2383 if (klass->nested_in) {
2384 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2385 /* get the typeref idx of the enclosing type */
2386 enclosing >>= MONO_TYPEDEFORREF_BITS;
2387 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2389 scope = resolution_scope_from_image (assembly, klass->image);
2391 table = &assembly->tables [MONO_TABLE_TYPEREF];
2392 if (assembly->save) {
2393 alloc_table (table, table->rows + 1);
2394 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2395 values [MONO_TYPEREF_SCOPE] = scope;
2396 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2397 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2399 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2400 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2402 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2407 * Despite the name, we handle also TypeSpec (with the above helper).
2410 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2412 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2415 #ifndef DISABLE_REFLECTION_EMIT
2417 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2419 MonoDynamicTable *table;
2421 guint32 token, pclass;
2423 switch (parent & MONO_TYPEDEFORREF_MASK) {
2424 case MONO_TYPEDEFORREF_TYPEREF:
2425 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2427 case MONO_TYPEDEFORREF_TYPESPEC:
2428 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2430 case MONO_TYPEDEFORREF_TYPEDEF:
2431 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2434 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2437 /* extract the index */
2438 parent >>= MONO_TYPEDEFORREF_BITS;
2440 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2442 if (assembly->save) {
2443 alloc_table (table, table->rows + 1);
2444 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2445 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2446 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2447 values [MONO_MEMBERREF_SIGNATURE] = sig;
2450 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2457 * Insert a memberef row into the metadata: the token that point to the memberref
2458 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2459 * mono_image_get_fieldref_token()).
2460 * The sig param is an index to an already built signature.
2463 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2465 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2466 return mono_image_add_memberef_row (assembly, parent, name, sig);
2471 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2474 MonoMethodSignature *sig;
2476 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2478 if (create_typespec) {
2479 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2485 if (token && !create_typespec)
2488 g_assert (!method->is_inflated);
2491 * A methodref signature can't contain an unmanaged calling convention.
2493 sig = mono_metadata_signature_dup (mono_method_signature (method));
2494 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2495 sig->call_convention = MONO_CALL_DEFAULT;
2496 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2497 method->name, method_encode_signature (assembly, sig));
2499 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2502 if (create_typespec) {
2503 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2504 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2505 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2507 if (assembly->save) {
2510 alloc_table (table, table->rows + 1);
2511 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2512 values [MONO_METHODSPEC_METHOD] = token;
2513 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2516 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2518 /*methodspec and memberef tokens are diferent, */
2519 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2526 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2528 guint32 token, parent, sig;
2529 ReflectionMethodBuilder rmb;
2531 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2533 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2537 name = mono_string_to_utf8 (method->name);
2538 reflection_methodbuilder_from_method_builder (&rmb, method);
2541 * A methodref signature can't contain an unmanaged calling convention.
2542 * Since some flags are encoded as part of call_conv, we need to check against it.
2544 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2545 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2547 sig = method_builder_encode_signature (assembly, &rmb);
2549 if (tb->generic_params)
2550 parent = create_generic_typespec (assembly, tb);
2552 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2554 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2557 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2562 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2563 const gchar *name, guint32 sig)
2565 MonoDynamicTable *table;
2569 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2571 if (assembly->save) {
2572 alloc_table (table, table->rows + 1);
2573 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2574 values [MONO_MEMBERREF_CLASS] = original;
2575 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2576 values [MONO_MEMBERREF_SIGNATURE] = sig;
2579 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2586 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2590 guint32 nparams = mono_array_length (mb->generic_params);
2593 if (!assembly->save)
2596 sigbuffer_init (&buf, 32);
2598 sigbuffer_add_value (&buf, 0xa);
2599 sigbuffer_add_value (&buf, nparams);
2601 for (i = 0; i < nparams; i++) {
2602 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2603 sigbuffer_add_value (&buf, i);
2606 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2607 sigbuffer_free (&buf);
2612 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2614 MonoDynamicTable *table;
2616 guint32 token, mtoken = 0;
2618 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2622 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2624 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2625 switch (mono_metadata_token_table (mtoken)) {
2626 case MONO_TABLE_MEMBERREF:
2627 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2629 case MONO_TABLE_METHOD:
2630 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2633 g_assert_not_reached ();
2636 if (assembly->save) {
2637 alloc_table (table, table->rows + 1);
2638 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2639 values [MONO_METHODSPEC_METHOD] = mtoken;
2640 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2643 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2646 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2651 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2655 if (mb->generic_params && create_methodspec)
2656 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2658 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2662 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2663 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2668 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2670 guint32 token, parent, sig;
2671 ReflectionMethodBuilder rmb;
2673 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2675 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2679 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2681 if (tb->generic_params)
2682 parent = create_generic_typespec (assembly, tb);
2684 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2686 name = mono_string_to_utf8 (rmb.name);
2687 sig = method_builder_encode_signature (assembly, &rmb);
2689 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2692 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2698 is_field_on_inst (MonoClassField *field)
2700 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2704 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2707 get_field_on_inst_generic_type (MonoClassField *field)
2709 MonoClass *class, *gtd;
2710 MonoDynamicGenericClass *dgclass;
2713 g_assert (is_field_on_inst (field));
2715 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2717 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2718 field_index = field - dgclass->fields;
2719 return dgclass->field_generic_types [field_index];
2722 class = field->parent;
2723 gtd = class->generic_class->container_class;
2725 if (field >= class->fields && field - class->fields < class->field.count) {
2726 field_index = field - class->fields;
2727 return gtd->fields [field_index].type;
2730 g_assert_not_reached ();
2734 #ifndef DISABLE_REFLECTION_EMIT
2736 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2742 g_assert (field->parent);
2744 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2748 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2749 int index = field - field->parent->fields;
2750 type = field->parent->generic_class->container_class->fields [index].type;
2752 if (is_field_on_inst (field))
2753 type = get_field_on_inst_generic_type (field);
2755 type = mono_field_get_type (field);
2757 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2758 mono_field_get_name (field),
2759 fieldref_encode_signature (assembly, field->parent->image, type));
2760 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2765 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2769 MonoGenericClass *gclass;
2770 MonoDynamicGenericClass *dgclass;
2774 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2777 if (is_sre_field_builder (mono_object_class (f->fb))) {
2778 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2779 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2780 klass = mono_class_from_mono_type (type);
2781 gclass = type->data.generic_class;
2782 g_assert (gclass->is_dynamic);
2783 dgclass = (MonoDynamicGenericClass *) gclass;
2785 name = mono_string_to_utf8 (fb->name);
2786 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2787 field_encode_signature (assembly, fb));
2789 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2791 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2793 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2794 klass = mono_class_from_mono_type (type);
2796 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2797 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2799 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2800 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2803 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2808 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2812 MonoGenericClass *gclass;
2815 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2817 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2821 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2822 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2823 MonoDynamicGenericClass *dgclass;
2824 ReflectionMethodBuilder rmb;
2827 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2828 klass = mono_class_from_mono_type (type);
2830 gclass = type->data.generic_class;
2831 g_assert (gclass->is_dynamic);
2832 dgclass = (MonoDynamicGenericClass *) gclass;
2834 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2836 name = mono_string_to_utf8 (rmb.name);
2838 sig = method_builder_encode_signature (assembly, &rmb);
2840 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2842 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2843 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2845 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2846 klass = mono_class_from_mono_type (type);
2848 sig = method_encode_signature (assembly, mono_method_signature (mm));
2849 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2851 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2852 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2856 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2861 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2864 MonoGenericContext tmp_context;
2865 MonoType **type_argv;
2866 MonoGenericInst *ginst;
2867 MonoMethod *method, *inflated;
2870 init_type_builder_generics ((MonoObject*)m->inst);
2872 method = inflate_method (m->inst, (MonoObject*)m->mb);
2874 klass = method->klass;
2876 if (m->method_args == NULL)
2879 if (method->is_inflated)
2880 method = ((MonoMethodInflated *) method)->declaring;
2882 count = mono_array_length (m->method_args);
2884 type_argv = g_new0 (MonoType *, count);
2885 for (i = 0; i < count; i++) {
2886 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2887 type_argv [i] = mono_reflection_type_get_handle (garg);
2889 ginst = mono_metadata_get_generic_inst (count, type_argv);
2892 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2893 tmp_context.method_inst = ginst;
2895 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2900 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2902 guint32 sig, token = 0;
2906 if (m->method_args) {
2907 MonoMethod *inflated;
2909 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2910 if (create_methodspec)
2911 token = mono_image_get_methodspec_token (assembly, inflated);
2913 token = mono_image_get_inflated_method_token (assembly, inflated);
2917 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2921 if (is_sre_method_builder (mono_object_class (m->mb))) {
2922 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2923 MonoGenericClass *gclass;
2924 ReflectionMethodBuilder rmb;
2927 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2928 klass = mono_class_from_mono_type (type);
2929 gclass = type->data.generic_class;
2930 g_assert (gclass->is_dynamic);
2932 reflection_methodbuilder_from_method_builder (&rmb, mb);
2934 name = mono_string_to_utf8 (rmb.name);
2936 sig = method_builder_encode_signature (assembly, &rmb);
2938 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2940 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2941 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2943 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2944 klass = mono_class_from_mono_type (type);
2946 sig = method_encode_signature (assembly, mono_method_signature (mm));
2947 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2949 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2950 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2953 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2958 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2962 guint32 nparams = context->method_inst->type_argc;
2965 if (!assembly->save)
2968 sigbuffer_init (&buf, 32);
2970 * FIXME: vararg, explicit_this, differenc call_conv values...
2972 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2973 sigbuffer_add_value (&buf, nparams);
2975 for (i = 0; i < nparams; i++)
2976 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2978 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2979 sigbuffer_free (&buf);
2984 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2986 MonoDynamicTable *table;
2988 guint32 token, mtoken = 0, sig;
2989 MonoMethodInflated *imethod;
2990 MonoMethod *declaring;
2992 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2994 g_assert (method->is_inflated);
2995 imethod = (MonoMethodInflated *) method;
2996 declaring = imethod->declaring;
2998 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2999 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3001 if (!mono_method_signature (declaring)->generic_param_count)
3004 switch (mono_metadata_token_table (mtoken)) {
3005 case MONO_TABLE_MEMBERREF:
3006 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3008 case MONO_TABLE_METHOD:
3009 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3012 g_assert_not_reached ();
3015 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3017 if (assembly->save) {
3018 alloc_table (table, table->rows + 1);
3019 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3020 values [MONO_METHODSPEC_METHOD] = mtoken;
3021 values [MONO_METHODSPEC_SIGNATURE] = sig;
3024 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3031 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3033 MonoMethodInflated *imethod;
3036 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3040 g_assert (method->is_inflated);
3041 imethod = (MonoMethodInflated *) method;
3043 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3044 token = method_encode_methodspec (assembly, method);
3046 guint32 sig = method_encode_signature (
3047 assembly, mono_method_signature (imethod->declaring));
3048 token = mono_image_get_memberref_token (
3049 assembly, &method->klass->byval_arg, method->name, sig);
3052 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3057 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3059 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3062 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3063 token = mono_image_get_memberref_token (
3064 assembly, &m->klass->byval_arg, m->name, sig);
3070 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3072 MonoDynamicTable *table;
3081 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3082 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3083 * Because of this, we must not insert it into the `typeref' hash table.
3085 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3086 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3090 sigbuffer_init (&buf, 32);
3092 g_assert (tb->generic_params);
3093 klass = mono_class_from_mono_type (type);
3095 if (tb->generic_container)
3096 mono_reflection_create_generic_class (tb);
3098 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3099 g_assert (klass->generic_container);
3100 sigbuffer_add_value (&buf, klass->byval_arg.type);
3101 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3103 count = mono_array_length (tb->generic_params);
3104 sigbuffer_add_value (&buf, count);
3105 for (i = 0; i < count; i++) {
3106 MonoReflectionGenericParam *gparam;
3108 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3110 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3113 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3115 if (assembly->save) {
3116 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3117 alloc_table (table, table->rows + 1);
3118 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3119 values [MONO_TYPESPEC_SIGNATURE] = token;
3121 sigbuffer_free (&buf);
3123 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3124 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3130 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3133 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3135 int i, count, len, pos;
3140 count += mono_array_length (modreq);
3142 count += mono_array_length (modopt);
3145 return mono_metadata_type_dup (NULL, type);
3147 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3149 memcpy (t, type, MONO_SIZEOF_TYPE);
3151 t->num_mods = count;
3154 for (i = 0; i < mono_array_length (modreq); ++i) {
3155 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3156 t->modifiers [pos].required = 1;
3157 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3162 for (i = 0; i < mono_array_length (modopt); ++i) {
3163 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3164 t->modifiers [pos].required = 0;
3165 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3174 init_type_builder_generics (MonoObject *type)
3176 MonoReflectionTypeBuilder *tb;
3178 if (!is_sre_type_builder(mono_object_class (type)))
3180 tb = (MonoReflectionTypeBuilder *)type;
3182 if (tb && tb->generic_container)
3183 mono_reflection_create_generic_class (tb);
3187 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3189 MonoDynamicTable *table;
3191 MonoType *custom = NULL, *type;
3193 guint32 token, pclass, parent, sig;
3196 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3200 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3201 name = mono_string_to_utf8 (fb->name);
3203 /*FIXME this is one more layer of ugliness due how types are created.*/
3204 init_type_builder_generics (fb->type);
3206 /* fb->type does not include the custom modifiers */
3207 /* FIXME: We should do this in one place when a fieldbuilder is created */
3208 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3209 if (fb->modreq || fb->modopt)
3210 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3212 sig = fieldref_encode_signature (assembly, NULL, type);
3215 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3216 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3218 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3219 parent >>= MONO_TYPEDEFORREF_BITS;
3221 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3223 if (assembly->save) {
3224 alloc_table (table, table->rows + 1);
3225 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3226 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3227 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3228 values [MONO_MEMBERREF_SIGNATURE] = sig;
3231 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3233 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3239 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3246 if (!assembly->save)
3249 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3250 g_assert (helper->type == 2);
3252 if (helper->arguments)
3253 nargs = mono_array_length (helper->arguments);
3257 size = 10 + (nargs * 10);
3259 sigbuffer_init (&buf, 32);
3261 /* Encode calling convention */
3262 /* Change Any to Standard */
3263 if ((helper->call_conv & 0x03) == 0x03)
3264 helper->call_conv = 0x01;
3265 /* explicit_this implies has_this */
3266 if (helper->call_conv & 0x40)
3267 helper->call_conv &= 0x20;
3269 if (helper->call_conv == 0) { /* Unmanaged */
3270 idx = helper->unmanaged_call_conv - 1;
3273 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3274 if (helper->call_conv & 0x02) /* varargs */
3278 sigbuffer_add_byte (&buf, idx);
3279 sigbuffer_add_value (&buf, nargs);
3280 encode_reflection_type (assembly, helper->return_type, &buf);
3281 for (i = 0; i < nargs; ++i) {
3282 MonoArray *modreqs = NULL;
3283 MonoArray *modopts = NULL;
3284 MonoReflectionType *pt;
3286 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3287 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3288 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3289 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3291 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3292 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3293 encode_reflection_type (assembly, pt, &buf);
3295 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3296 sigbuffer_free (&buf);
3302 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3305 MonoDynamicTable *table;
3308 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3309 idx = table->next_idx ++;
3311 alloc_table (table, table->rows);
3312 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3314 values [MONO_STAND_ALONE_SIGNATURE] =
3315 mono_reflection_encode_sighelper (assembly, helper);
3321 reflection_cc_to_file (int call_conv) {
3322 switch (call_conv & 0x3) {
3324 case 1: return MONO_CALL_DEFAULT;
3325 case 2: return MONO_CALL_VARARG;
3327 g_assert_not_reached ();
3331 #endif /* !DISABLE_REFLECTION_EMIT */
3335 MonoMethodSignature *sig;
3340 #ifndef DISABLE_REFLECTION_EMIT
3342 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3347 MonoMethodSignature *sig;
3351 name = mono_string_to_utf8 (m->name);
3352 nparams = mono_array_length (m->parameters);
3353 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3355 sig->sentinelpos = -1;
3356 sig->call_convention = reflection_cc_to_file (m->call_conv);
3357 sig->param_count = nparams;
3358 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3359 mtype = mono_reflection_type_get_handle (m->parent);
3360 for (i = 0; i < nparams; ++i)
3361 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3363 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3365 if (strcmp (name, am->name) == 0 &&
3366 mono_metadata_type_equal (am->parent, mtype) &&
3367 mono_metadata_signature_equal (am->sig, sig)) {
3370 m->table_idx = am->token & 0xffffff;
3374 am = g_new0 (ArrayMethod, 1);
3378 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3379 method_encode_signature (assembly, sig));
3380 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3381 m->table_idx = am->token & 0xffffff;
3386 * Insert into the metadata tables all the info about the TypeBuilder tb.
3387 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3390 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3392 MonoDynamicTable *table;
3394 int i, is_object = 0, is_system = 0;
3397 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3398 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3399 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3400 n = mono_string_to_utf8 (tb->name);
3401 if (strcmp (n, "Object") == 0)
3403 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3405 n = mono_string_to_utf8 (tb->nspace);
3406 if (strcmp (n, "System") == 0)
3408 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3410 if (tb->parent && !(is_system && is_object) &&
3411 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3412 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3414 values [MONO_TYPEDEF_EXTENDS] = 0;
3416 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3417 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3420 * if we have explicitlayout or sequentiallayouts, output data in the
3421 * ClassLayout table.
3423 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3424 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3425 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3427 alloc_table (table, table->rows);
3428 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3429 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3430 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3431 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3434 /* handle interfaces */
3435 if (tb->interfaces) {
3436 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3438 table->rows += mono_array_length (tb->interfaces);
3439 alloc_table (table, table->rows);
3440 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3441 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3442 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3443 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3444 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3445 values += MONO_INTERFACEIMPL_SIZE;
3451 table = &assembly->tables [MONO_TABLE_FIELD];
3452 table->rows += tb->num_fields;
3453 alloc_table (table, table->rows);
3454 for (i = 0; i < tb->num_fields; ++i)
3455 mono_image_get_field_info (
3456 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3459 /* handle constructors */
3461 table = &assembly->tables [MONO_TABLE_METHOD];
3462 table->rows += mono_array_length (tb->ctors);
3463 alloc_table (table, table->rows);
3464 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3465 mono_image_get_ctor_info (domain,
3466 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3469 /* handle methods */
3471 table = &assembly->tables [MONO_TABLE_METHOD];
3472 table->rows += tb->num_methods;
3473 alloc_table (table, table->rows);
3474 for (i = 0; i < tb->num_methods; ++i)
3475 mono_image_get_method_info (
3476 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3479 /* Do the same with properties etc.. */
3480 if (tb->events && mono_array_length (tb->events)) {
3481 table = &assembly->tables [MONO_TABLE_EVENT];
3482 table->rows += mono_array_length (tb->events);
3483 alloc_table (table, table->rows);
3484 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3486 alloc_table (table, table->rows);
3487 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3488 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3489 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3490 for (i = 0; i < mono_array_length (tb->events); ++i)
3491 mono_image_get_event_info (
3492 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3494 if (tb->properties && mono_array_length (tb->properties)) {
3495 table = &assembly->tables [MONO_TABLE_PROPERTY];
3496 table->rows += mono_array_length (tb->properties);
3497 alloc_table (table, table->rows);
3498 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3500 alloc_table (table, table->rows);
3501 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3502 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3503 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3504 for (i = 0; i < mono_array_length (tb->properties); ++i)
3505 mono_image_get_property_info (
3506 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3509 /* handle generic parameters */
3510 if (tb->generic_params) {
3511 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3512 table->rows += mono_array_length (tb->generic_params);
3513 alloc_table (table, table->rows);
3514 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3515 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3517 mono_image_get_generic_param_info (
3518 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3522 mono_image_add_decl_security (assembly,
3523 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3526 MonoDynamicTable *ntable;
3528 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3529 ntable->rows += mono_array_length (tb->subtypes);
3530 alloc_table (ntable, ntable->rows);
3531 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3533 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3534 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3536 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3537 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3538 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3539 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3540 mono_string_to_utf8 (tb->name), tb->table_idx,
3541 ntable->next_idx, ntable->rows);*/
3542 values += MONO_NESTED_CLASS_SIZE;
3550 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3554 mono_ptr_array_append (*types, type);
3556 if (!type->subtypes)
3559 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3560 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3561 collect_types (types, subtype);
3566 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3568 if ((*type1)->table_idx < (*type2)->table_idx)
3571 if ((*type1)->table_idx > (*type2)->table_idx)
3578 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3583 for (i = 0; i < mono_array_length (pinfo); ++i) {
3584 MonoReflectionParamBuilder *pb;
3585 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3588 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3593 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3596 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3598 for (i = 0; i < tb->num_fields; ++i) {
3599 MonoReflectionFieldBuilder* fb;
3600 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3601 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3605 for (i = 0; i < mono_array_length (tb->events); ++i) {
3606 MonoReflectionEventBuilder* eb;
3607 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3608 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3611 if (tb->properties) {
3612 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3613 MonoReflectionPropertyBuilder* pb;
3614 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3615 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3619 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3620 MonoReflectionCtorBuilder* cb;
3621 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3622 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3623 params_add_cattrs (assembly, cb->pinfo);
3628 for (i = 0; i < tb->num_methods; ++i) {
3629 MonoReflectionMethodBuilder* mb;
3630 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3631 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3632 params_add_cattrs (assembly, mb->pinfo);
3637 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3638 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3643 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3647 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3649 if (moduleb->global_methods) {
3650 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3651 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3652 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3653 params_add_cattrs (assembly, mb->pinfo);
3657 if (moduleb->global_fields) {
3658 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3659 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3660 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3664 if (moduleb->types) {
3665 for (i = 0; i < moduleb->num_types; ++i)
3666 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3671 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3673 MonoDynamicTable *table;
3677 char *b = blob_size;
3680 table = &assembly->tables [MONO_TABLE_FILE];
3682 alloc_table (table, table->rows);
3683 values = table->values + table->next_idx * MONO_FILE_SIZE;
3684 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3685 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3686 if (module->image->dynamic) {
3687 /* This depends on the fact that the main module is emitted last */
3688 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3689 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3692 path = g_strdup (module->image->name);
3694 mono_sha1_get_digest_from_file (path, hash);
3697 mono_metadata_encode_value (20, b, &b);
3698 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3699 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3704 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3706 MonoDynamicTable *table;
3709 table = &assembly->tables [MONO_TABLE_MODULE];
3710 mb->table_idx = table->next_idx ++;
3711 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3712 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3715 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3716 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3717 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3718 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3722 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3723 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3725 MonoDynamicTable *table;
3729 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3730 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3733 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3735 alloc_table (table, table->rows);
3736 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3738 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3739 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3740 if (klass->nested_in)
3741 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3743 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3744 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3745 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3747 res = table->next_idx;
3751 /* Emit nested types */
3752 if (klass->ext && klass->ext->nested_classes) {
3755 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3756 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3763 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3764 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3769 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3771 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3773 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3774 parent_index, assembly);
3778 * We need to do this ourselves since klass->nested_classes is not set up.
3781 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3782 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3787 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3788 guint32 module_index, MonoDynamicImage *assembly)
3790 MonoImage *image = module->image;
3794 t = &image->tables [MONO_TABLE_TYPEDEF];
3796 for (i = 0; i < t->rows; ++i) {
3797 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3799 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3800 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3805 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3807 MonoDynamicTable *table;
3809 guint32 scope, scope_idx, impl, current_idx;
3810 gboolean forwarder = TRUE;
3811 gpointer iter = NULL;
3814 if (klass->nested_in) {
3815 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3818 scope = resolution_scope_from_image (assembly, klass->image);
3819 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3820 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3821 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3824 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3827 alloc_table (table, table->rows);
3828 current_idx = table->next_idx;
3829 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3831 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3832 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3833 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3834 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3835 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3839 while ((nested = mono_class_get_nested_types (klass, &iter)))
3840 add_exported_type (assemblyb, assembly, nested, current_idx);
3844 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3849 if (!assemblyb->type_forwarders)
3852 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3853 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3858 type = mono_reflection_type_get_handle (t);
3861 klass = mono_class_from_mono_type (type);
3863 add_exported_type (assemblyb, assembly, klass, 0);
3867 #define align_pointer(base,p)\
3869 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3871 (p) += 4 - (__diff & 3);\
3875 compare_constants (const void *a, const void *b)
3877 const guint32 *a_values = a;
3878 const guint32 *b_values = b;
3879 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3883 compare_semantics (const void *a, const void *b)
3885 const guint32 *a_values = a;
3886 const guint32 *b_values = b;
3887 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3890 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3894 compare_custom_attrs (const void *a, const void *b)
3896 const guint32 *a_values = a;
3897 const guint32 *b_values = b;
3899 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3903 compare_field_marshal (const void *a, const void *b)
3905 const guint32 *a_values = a;
3906 const guint32 *b_values = b;
3908 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3912 compare_nested (const void *a, const void *b)
3914 const guint32 *a_values = a;
3915 const guint32 *b_values = b;
3917 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3921 compare_genericparam (const void *a, const void *b)
3923 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3924 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3926 if ((*b_entry)->owner == (*a_entry)->owner)
3928 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3929 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3931 return (*a_entry)->owner - (*b_entry)->owner;
3935 compare_declsecurity_attrs (const void *a, const void *b)
3937 const guint32 *a_values = a;
3938 const guint32 *b_values = b;
3940 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3944 compare_interface_impl (const void *a, const void *b)
3946 const guint32 *a_values = a;
3947 const guint32 *b_values = b;
3949 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3953 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3957 pad_heap (MonoDynamicStream *sh)
3959 if (sh->index & 3) {
3960 int sz = 4 - (sh->index & 3);
3961 memset (sh->data + sh->index, 0, sz);
3968 MonoDynamicStream *stream;
3972 * build_compressed_metadata() fills in the blob of data that represents the
3973 * raw metadata as it will be saved in the PE file. The five streams are output
3974 * and the metadata tables are comnpressed from the guint32 array representation,
3975 * to the compressed on-disk format.
3978 build_compressed_metadata (MonoDynamicImage *assembly)
3980 MonoDynamicTable *table;
3982 guint64 valid_mask = 0;
3983 guint64 sorted_mask;
3984 guint32 heapt_size = 0;
3985 guint32 meta_size = 256; /* allow for header and other stuff */
3986 guint32 table_offset;
3987 guint32 ntables = 0;
3993 struct StreamDesc stream_desc [5];
3995 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3996 for (i = 0; i < assembly->gen_params->len; i++){
3997 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3998 write_generic_param_entry (assembly, entry);
4001 stream_desc [0].name = "#~";
4002 stream_desc [0].stream = &assembly->tstream;
4003 stream_desc [1].name = "#Strings";
4004 stream_desc [1].stream = &assembly->sheap;
4005 stream_desc [2].name = "#US";
4006 stream_desc [2].stream = &assembly->us;
4007 stream_desc [3].name = "#Blob";
4008 stream_desc [3].stream = &assembly->blob;
4009 stream_desc [4].name = "#GUID";
4010 stream_desc [4].stream = &assembly->guid;
4012 /* tables that are sorted */
4013 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4014 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4015 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4016 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4017 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4018 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4019 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4021 /* Compute table sizes */
4022 /* the MonoImage has already been created in mono_image_basic_init() */
4023 meta = &assembly->image;
4025 /* sizes should be multiple of 4 */
4026 pad_heap (&assembly->blob);
4027 pad_heap (&assembly->guid);
4028 pad_heap (&assembly->sheap);
4029 pad_heap (&assembly->us);
4031 /* Setup the info used by compute_sizes () */
4032 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4033 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4034 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4036 meta_size += assembly->blob.index;
4037 meta_size += assembly->guid.index;
4038 meta_size += assembly->sheap.index;
4039 meta_size += assembly->us.index;
4041 for (i=0; i < MONO_TABLE_NUM; ++i)
4042 meta->tables [i].rows = assembly->tables [i].rows;
4044 for (i = 0; i < MONO_TABLE_NUM; i++){
4045 if (meta->tables [i].rows == 0)
4047 valid_mask |= (guint64)1 << i;
4049 meta->tables [i].row_size = mono_metadata_compute_size (
4050 meta, i, &meta->tables [i].size_bitfield);
4051 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4053 heapt_size += 24; /* #~ header size */
4054 heapt_size += ntables * 4;
4055 /* make multiple of 4 */
4058 meta_size += heapt_size;
4059 meta->raw_metadata = g_malloc0 (meta_size);
4060 p = (unsigned char*)meta->raw_metadata;
4061 /* the metadata signature */
4062 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4063 /* version numbers and 4 bytes reserved */
4064 int16val = (guint16*)p;
4065 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4066 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4068 /* version string */
4069 int32val = (guint32*)p;
4070 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4072 memcpy (p, meta->version, strlen (meta->version));
4073 p += GUINT32_FROM_LE (*int32val);
4074 align_pointer (meta->raw_metadata, p);
4075 int16val = (guint16*)p;
4076 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4077 *int16val = GUINT16_TO_LE (5); /* number of streams */
4081 * write the stream info.
4083 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4084 table_offset += 3; table_offset &= ~3;
4086 assembly->tstream.index = heapt_size;
4087 for (i = 0; i < 5; ++i) {
4088 int32val = (guint32*)p;
4089 stream_desc [i].stream->offset = table_offset;
4090 *int32val++ = GUINT32_TO_LE (table_offset);
4091 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4092 table_offset += GUINT32_FROM_LE (*int32val);
4093 table_offset += 3; table_offset &= ~3;
4095 strcpy ((char*)p, stream_desc [i].name);
4096 p += strlen (stream_desc [i].name) + 1;
4097 align_pointer (meta->raw_metadata, p);
4100 * now copy the data, the table stream header and contents goes first.
4102 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4103 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4104 int32val = (guint32*)p;
4105 *int32val = GUINT32_TO_LE (0); /* reserved */
4108 *p++ = 2; /* version */
4111 if (meta->idx_string_wide)
4113 if (meta->idx_guid_wide)
4115 if (meta->idx_blob_wide)
4118 *p++ = 1; /* reserved */
4119 int64val = (guint64*)p;
4120 *int64val++ = GUINT64_TO_LE (valid_mask);
4121 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4123 int32val = (guint32*)p;
4124 for (i = 0; i < MONO_TABLE_NUM; i++){
4125 if (meta->tables [i].rows == 0)
4127 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4129 p = (unsigned char*)int32val;
4131 /* sort the tables that still need sorting */
4132 table = &assembly->tables [MONO_TABLE_CONSTANT];
4134 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4135 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4137 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4138 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4140 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4141 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4143 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4144 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4146 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4147 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4148 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4150 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4151 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4153 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4155 /* compress the tables */
4156 for (i = 0; i < MONO_TABLE_NUM; i++){
4159 guint32 bitfield = meta->tables [i].size_bitfield;
4160 if (!meta->tables [i].rows)
4162 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4163 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4164 meta->tables [i].base = (char*)p;
4165 for (row = 1; row <= meta->tables [i].rows; ++row) {
4166 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4167 for (col = 0; col < assembly->tables [i].columns; ++col) {
4168 switch (mono_metadata_table_size (bitfield, col)) {
4170 *p++ = values [col];
4173 *p++ = values [col] & 0xff;
4174 *p++ = (values [col] >> 8) & 0xff;
4177 *p++ = values [col] & 0xff;
4178 *p++ = (values [col] >> 8) & 0xff;
4179 *p++ = (values [col] >> 16) & 0xff;
4180 *p++ = (values [col] >> 24) & 0xff;
4183 g_assert_not_reached ();
4187 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4190 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4191 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4192 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4193 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4194 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4196 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4200 * Some tables in metadata need to be sorted according to some criteria, but
4201 * when methods and fields are first created with reflection, they may be assigned a token
4202 * that doesn't correspond to the final token they will get assigned after the sorting.
4203 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4204 * with the reflection objects that represent them. Once all the tables are set up, the
4205 * reflection objects will contains the correct table index. fixup_method() will fixup the
4206 * tokens for the method with ILGenerator @ilgen.
4209 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4211 guint32 code_idx = GPOINTER_TO_UINT (value);
4212 MonoReflectionILTokenInfo *iltoken;
4213 MonoReflectionFieldBuilder *field;
4214 MonoReflectionCtorBuilder *ctor;
4215 MonoReflectionMethodBuilder *method;
4216 MonoReflectionTypeBuilder *tb;
4217 MonoReflectionArrayMethod *am;
4219 unsigned char *target;
4221 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4222 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4223 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4224 switch (target [3]) {
4225 case MONO_TABLE_FIELD:
4226 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4227 field = (MonoReflectionFieldBuilder *)iltoken->member;
4228 idx = field->table_idx;
4229 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4230 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4231 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4233 g_assert_not_reached ();
4236 case MONO_TABLE_METHOD:
4237 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4238 method = (MonoReflectionMethodBuilder *)iltoken->member;
4239 idx = method->table_idx;
4240 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4241 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4242 idx = ctor->table_idx;
4243 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4244 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4245 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4246 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4248 g_assert_not_reached ();
4251 case MONO_TABLE_TYPEDEF:
4252 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4253 g_assert_not_reached ();
4254 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4255 idx = tb->table_idx;
4257 case MONO_TABLE_MEMBERREF:
4258 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4259 am = (MonoReflectionArrayMethod*)iltoken->member;
4260 idx = am->table_idx;
4261 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4262 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4263 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4264 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4265 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4266 g_assert (m->klass->generic_class || m->klass->generic_container);
4268 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4270 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4271 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4272 g_assert (is_field_on_inst (f));
4274 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4275 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4277 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4279 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4281 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4284 g_assert_not_reached ();
4287 case MONO_TABLE_METHODSPEC:
4288 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4289 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4290 g_assert (mono_method_signature (m)->generic_param_count);
4292 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4294 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4297 g_assert_not_reached ();
4301 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4303 target [0] = idx & 0xff;
4304 target [1] = (idx >> 8) & 0xff;
4305 target [2] = (idx >> 16) & 0xff;
4312 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4313 * value is not known when the table is emitted.
4316 fixup_cattrs (MonoDynamicImage *assembly)
4318 MonoDynamicTable *table;
4320 guint32 type, i, idx, token;
4323 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4325 for (i = 0; i < table->rows; ++i) {
4326 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4328 type = values [MONO_CUSTOM_ATTR_TYPE];
4329 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4330 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4331 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4332 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4335 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")|| !strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4336 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4337 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4338 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4345 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4347 MonoDynamicTable *table;
4350 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4352 alloc_table (table, table->rows);
4353 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4354 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4355 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4356 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4357 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4362 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4364 MonoDynamicTable *table;
4368 char *b = blob_size;
4370 guint32 idx, offset;
4372 if (rsrc->filename) {
4373 name = mono_string_to_utf8 (rsrc->filename);
4374 sname = g_path_get_basename (name);
4376 table = &assembly->tables [MONO_TABLE_FILE];
4378 alloc_table (table, table->rows);
4379 values = table->values + table->next_idx * MONO_FILE_SIZE;
4380 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4381 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4384 mono_sha1_get_digest_from_file (name, hash);
4385 mono_metadata_encode_value (20, b, &b);
4386 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4387 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4389 idx = table->next_idx++;
4391 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4397 data = mono_array_addr (rsrc->data, char, 0);
4398 len = mono_array_length (rsrc->data);
4404 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4405 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4406 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4407 mono_image_add_stream_data (&assembly->resources, data, len);
4411 * The entry should be emitted into the MANIFESTRESOURCE table of
4412 * the main module, but that needs to reference the FILE table
4413 * which isn't emitted yet.
4420 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4424 set_version_from_string (MonoString *version, guint32 *values)
4426 gchar *ver, *p, *str;
4429 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4430 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4431 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4432 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4435 ver = str = mono_string_to_utf8 (version);
4436 for (i = 0; i < 4; ++i) {
4437 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4443 /* handle Revision and Build */
4453 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4457 char *b = blob_size;
4462 len = mono_array_length (pkey);
4463 mono_metadata_encode_value (len, b, &b);
4464 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4465 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4467 assembly->public_key = g_malloc (len);
4468 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4469 assembly->public_key_len = len;
4471 /* Special case: check for ECMA key (16 bytes) */
4472 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4473 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4474 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4475 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4476 /* minimum key size (in 2.0) is 384 bits */
4477 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4479 /* FIXME - verifier */
4480 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4481 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4483 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4489 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4491 MonoDynamicTable *table;
4492 MonoDynamicImage *assembly;
4493 MonoReflectionAssemblyBuilder *assemblyb;
4497 guint32 module_index;
4499 assemblyb = moduleb->assemblyb;
4500 assembly = moduleb->dynamic_image;
4501 domain = mono_object_domain (assemblyb);
4503 /* Emit ASSEMBLY table */
4504 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4505 alloc_table (table, 1);
4506 values = table->values + MONO_ASSEMBLY_SIZE;
4507 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4508 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4509 if (assemblyb->culture) {
4510 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4512 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4514 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4515 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4516 set_version_from_string (assemblyb->version, values);
4518 /* Emit FILE + EXPORTED_TYPE table */
4520 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4522 MonoReflectionModuleBuilder *file_module =
4523 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4524 if (file_module != moduleb) {
4525 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4527 if (file_module->types) {
4528 for (j = 0; j < file_module->num_types; ++j) {
4529 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4530 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4535 if (assemblyb->loaded_modules) {
4536 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4537 MonoReflectionModule *file_module =
4538 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4539 mono_image_fill_file_table (domain, file_module, assembly);
4541 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4544 if (assemblyb->type_forwarders)
4545 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4547 /* Emit MANIFESTRESOURCE table */
4549 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4551 MonoReflectionModuleBuilder *file_module =
4552 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4553 /* The table for the main module is emitted later */
4554 if (file_module != moduleb) {
4556 if (file_module->resources) {
4557 int len = mono_array_length (file_module->resources);
4558 for (j = 0; j < len; ++j) {
4559 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4560 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4567 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4570 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4571 * for the modulebuilder @moduleb.
4572 * At the end of the process, method and field tokens are fixed up and the
4573 * on-disk compressed metadata representation is created.
4576 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4578 MonoDynamicTable *table;
4579 MonoDynamicImage *assembly;
4580 MonoReflectionAssemblyBuilder *assemblyb;
4586 assemblyb = moduleb->assemblyb;
4587 assembly = moduleb->dynamic_image;
4588 domain = mono_object_domain (assemblyb);
4590 if (assembly->text_rva)
4593 assembly->text_rva = START_TEXT_RVA;
4595 if (moduleb->is_main) {
4596 mono_image_emit_manifest (moduleb);
4599 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4600 table->rows = 1; /* .<Module> */
4602 alloc_table (table, table->rows);
4604 * Set the first entry.
4606 values = table->values + table->columns;
4607 values [MONO_TYPEDEF_FLAGS] = 0;
4608 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4609 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4610 values [MONO_TYPEDEF_EXTENDS] = 0;
4611 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4612 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4615 * handle global methods
4616 * FIXME: test what to do when global methods are defined in multiple modules.
4618 if (moduleb->global_methods) {
4619 table = &assembly->tables [MONO_TABLE_METHOD];
4620 table->rows += mono_array_length (moduleb->global_methods);
4621 alloc_table (table, table->rows);
4622 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4623 mono_image_get_method_info (
4624 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4626 if (moduleb->global_fields) {
4627 table = &assembly->tables [MONO_TABLE_FIELD];
4628 table->rows += mono_array_length (moduleb->global_fields);
4629 alloc_table (table, table->rows);
4630 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4631 mono_image_get_field_info (
4632 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4635 table = &assembly->tables [MONO_TABLE_MODULE];
4636 alloc_table (table, 1);
4637 mono_image_fill_module_table (domain, moduleb, assembly);
4639 /* Collect all types into a list sorted by their table_idx */
4640 mono_ptr_array_init (types, moduleb->num_types);
4643 for (i = 0; i < moduleb->num_types; ++i) {
4644 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4645 collect_types (&types, type);
4648 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4649 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4650 table->rows += mono_ptr_array_size (types);
4651 alloc_table (table, table->rows);
4654 * Emit type names + namespaces at one place inside the string heap,
4655 * so load_class_names () needs to touch fewer pages.
4657 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4658 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4659 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4661 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4662 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4663 string_heap_insert_mstring (&assembly->sheap, tb->name);
4666 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4668 mono_image_get_type_info (domain, type, assembly);
4672 * table->rows is already set above and in mono_image_fill_module_table.
4674 /* add all the custom attributes at the end, once all the indexes are stable */
4675 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4677 /* CAS assembly permissions */
4678 if (assemblyb->permissions_minimum)
4679 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4680 if (assemblyb->permissions_optional)
4681 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4682 if (assemblyb->permissions_refused)
4683 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4685 module_add_cattrs (assembly, moduleb);
4688 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4690 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4691 * the final tokens and don't need another fixup pass. */
4693 if (moduleb->global_methods) {
4694 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4695 MonoReflectionMethodBuilder *mb = mono_array_get (
4696 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4697 mono_image_add_methodimpl (assembly, mb);
4701 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4702 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4703 if (type->methods) {
4704 for (j = 0; j < type->num_methods; ++j) {
4705 MonoReflectionMethodBuilder *mb = mono_array_get (
4706 type->methods, MonoReflectionMethodBuilder*, j);
4708 mono_image_add_methodimpl (assembly, mb);
4713 mono_ptr_array_destroy (types);
4715 fixup_cattrs (assembly);
4718 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4721 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4723 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4726 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4730 guint32 import_lookup_table;
4734 guint32 import_address_table_rva;
4742 #ifndef DISABLE_REFLECTION_EMIT
4745 * mono_image_insert_string:
4746 * @module: module builder object
4749 * Insert @str into the user string stream of @module.
4752 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4754 MonoDynamicImage *assembly;
4759 MONO_ARCH_SAVE_REGS;
4761 if (!module->dynamic_image)
4762 mono_image_module_basic_init (module);
4764 assembly = module->dynamic_image;
4766 if (assembly->save) {
4767 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4768 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4769 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4771 char *swapped = g_malloc (2 * mono_string_length (str));
4772 const char *p = (const char*)mono_string_chars (str);
4774 swap_with_size (swapped, p, 2, mono_string_length (str));
4775 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4779 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4781 mono_image_add_stream_data (&assembly->us, "", 1);
4783 idx = assembly->us.index ++;
4786 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4788 return MONO_TOKEN_STRING | idx;
4792 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4796 MonoMethodSignature *sig;
4798 klass = obj->vtable->klass;
4799 if (strcmp (klass->name, "MonoMethod") == 0) {
4800 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4801 MonoMethodSignature *old;
4802 guint32 sig_token, parent;
4805 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4807 nargs = mono_array_length (opt_param_types);
4808 old = mono_method_signature (method);
4809 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4811 sig->hasthis = old->hasthis;
4812 sig->explicit_this = old->explicit_this;
4813 sig->call_convention = old->call_convention;
4814 sig->generic_param_count = old->generic_param_count;
4815 sig->param_count = old->param_count + nargs;
4816 sig->sentinelpos = old->param_count;
4817 sig->ret = old->ret;
4819 for (i = 0; i < old->param_count; i++)
4820 sig->params [i] = old->params [i];
4822 for (i = 0; i < nargs; i++) {
4823 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4824 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4827 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4828 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4829 parent >>= MONO_TYPEDEFORREF_BITS;
4831 parent <<= MONO_MEMBERREF_PARENT_BITS;
4832 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4834 sig_token = method_encode_signature (assembly, sig);
4835 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4836 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4837 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4838 ReflectionMethodBuilder rmb;
4839 guint32 parent, sig_token;
4840 int nopt_args, nparams, ngparams, i;
4843 reflection_methodbuilder_from_method_builder (&rmb, mb);
4844 rmb.opt_types = opt_param_types;
4845 nopt_args = mono_array_length (opt_param_types);
4847 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4848 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4849 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4851 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4852 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4853 sig->call_convention = rmb.call_conv;
4854 sig->generic_param_count = ngparams;
4855 sig->param_count = nparams + nopt_args;
4856 sig->sentinelpos = nparams;
4857 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4859 for (i = 0; i < nparams; i++) {
4860 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4861 sig->params [i] = mono_reflection_type_get_handle (rt);
4864 for (i = 0; i < nopt_args; i++) {
4865 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4866 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4869 sig_token = method_builder_encode_signature (assembly, &rmb);
4871 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4872 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4874 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4875 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4877 name = mono_string_to_utf8 (rmb.name);
4878 token = mono_image_get_varargs_method_token (
4879 assembly, parent, name, sig_token);
4882 g_error ("requested method token for %s\n", klass->name);
4885 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4886 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4891 * mono_image_create_token:
4892 * @assembly: a dynamic assembly
4894 * @register_token: Whenever to register the token in the assembly->tokens hash.
4896 * Get a token to insert in the IL code stream for the given MemberInfo.
4897 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4898 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4902 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4903 gboolean create_open_instance, gboolean register_token)
4908 klass = obj->vtable->klass;
4910 /* Check for user defined reflection objects */
4911 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4912 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4913 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4915 if (strcmp (klass->name, "MethodBuilder") == 0) {
4916 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4917 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4919 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4920 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4922 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4923 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4924 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4925 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4926 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4928 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4929 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4931 token = mono_image_get_ctorbuilder_token (assembly, mb);
4932 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4933 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4934 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4935 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4936 if (tb->generic_params) {
4937 token = mono_image_get_generic_field_token (assembly, fb);
4939 if (tb->module->dynamic_image == assembly) {
4940 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4942 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4945 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4946 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4947 if (create_open_instance && tb->generic_params) {
4949 init_type_builder_generics (obj);
4950 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4951 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4952 token = mono_metadata_token_from_dor (token);
4953 } else if (tb->module->dynamic_image == assembly) {
4954 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4957 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4958 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4960 } else if (strcmp (klass->name, "MonoType") == 0) {
4961 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4962 MonoClass *mc = mono_class_from_mono_type (type);
4963 token = mono_metadata_token_from_dor (
4964 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4965 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4966 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967 token = mono_metadata_token_from_dor (
4968 mono_image_typedef_or_ref (assembly, type));
4969 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4970 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4971 token = mono_metadata_token_from_dor (
4972 mono_image_typedef_or_ref (assembly, type));
4973 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4974 strcmp (klass->name, "MonoMethod") == 0 ||
4975 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4976 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4977 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4978 if (m->method->is_inflated) {
4979 if (create_open_instance)
4980 token = mono_image_get_methodspec_token (assembly, m->method);
4982 token = mono_image_get_inflated_method_token (assembly, m->method);
4983 } else if ((m->method->klass->image == &assembly->image) &&
4984 !m->method->klass->generic_class) {
4985 static guint32 method_table_idx = 0xffffff;
4986 if (m->method->klass->wastypebuilder) {
4987 /* we use the same token as the one that was assigned
4988 * to the Methodbuilder.
4989 * FIXME: do the equivalent for Fields.
4991 token = m->method->token;
4994 * Each token should have a unique index, but the indexes are
4995 * assigned by managed code, so we don't know about them. An
4996 * easy solution is to count backwards...
4998 method_table_idx --;
4999 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5002 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5004 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5005 } else if (strcmp (klass->name, "MonoField") == 0) {
5006 MonoReflectionField *f = (MonoReflectionField *)obj;
5007 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5008 static guint32 field_table_idx = 0xffffff;
5010 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5012 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5014 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5015 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5016 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5017 token = mono_image_get_array_token (assembly, m);
5018 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5019 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5020 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5021 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5022 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5023 token = mono_metadata_token_from_dor (
5024 mono_image_typedef_or_ref (assembly, type));
5025 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5026 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5027 token = mono_image_get_field_on_inst_token (assembly, f);
5028 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5029 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5030 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5031 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5032 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5033 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5034 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5035 MonoReflectionType *type = (MonoReflectionType *)obj;
5036 token = mono_metadata_token_from_dor (
5037 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5039 g_error ("requested token for %s\n", klass->name);
5043 mono_image_register_token (assembly, token, obj);
5049 * mono_image_register_token:
5051 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5052 * the Module.ResolveXXXToken () methods to work.
5055 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5057 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5059 /* There could be multiple MethodInfo objects with the same token */
5060 //g_assert (prev == obj);
5062 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5066 static MonoDynamicImage*
5067 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5069 static const guchar entrycode [16] = {0xff, 0x25, 0};
5070 MonoDynamicImage *image;
5073 const char *version;
5075 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5076 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5078 version = mono_get_runtime_info ()->runtime_version;
5081 /* The MonoGHashTable's need GC tracking */
5082 image = GC_MALLOC (sizeof (MonoDynamicImage));
5084 image = g_new0 (MonoDynamicImage, 1);
5087 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5089 /*g_print ("created image %p\n", image);*/
5090 /* keep in sync with image.c */
5091 image->image.name = assembly_name;
5092 image->image.assembly_name = image->image.name; /* they may be different */
5093 image->image.module_name = module_name;
5094 image->image.version = g_strdup (version);
5095 image->image.md_version_major = 1;
5096 image->image.md_version_minor = 1;
5097 image->image.dynamic = TRUE;
5099 image->image.references = g_new0 (MonoAssembly*, 1);
5100 image->image.references [0] = NULL;
5102 mono_image_init (&image->image);
5104 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5105 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5106 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5107 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5108 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5109 image->handleref = g_hash_table_new (NULL, NULL);
5110 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5111 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5112 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5113 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5114 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5115 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5116 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5117 image->gen_params = g_ptr_array_new ();
5119 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5120 string_heap_init (&image->sheap);
5121 mono_image_add_stream_data (&image->us, "", 1);
5122 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5123 /* import tables... */
5124 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5125 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5126 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5127 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5128 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5129 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5130 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5131 stream_data_align (&image->code);
5133 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5135 for (i=0; i < MONO_TABLE_NUM; ++i) {
5136 image->tables [i].next_idx = 1;
5137 image->tables [i].columns = table_sizes [i];
5140 image->image.assembly = (MonoAssembly*)assembly;
5141 image->run = assembly->run;
5142 image->save = assembly->save;
5143 image->pe_kind = 0x1; /* ILOnly */
5144 image->machine = 0x14c; /* I386 */
5146 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5153 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5159 release_hashtable (MonoGHashTable **hash)
5162 mono_g_hash_table_destroy (*hash);
5168 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5170 release_hashtable (&image->token_fixups);
5171 release_hashtable (&image->handleref_managed);
5172 release_hashtable (&image->tokens);
5173 release_hashtable (&image->generic_def_objects);
5174 release_hashtable (&image->methodspec);
5178 mono_dynamic_image_free (MonoDynamicImage *image)
5180 MonoDynamicImage *di = image;
5185 mono_g_hash_table_destroy (di->methodspec);
5187 g_hash_table_destroy (di->typespec);
5189 g_hash_table_destroy (di->typeref);
5191 g_hash_table_destroy (di->handleref);
5192 if (di->handleref_managed)
5193 mono_g_hash_table_destroy (di->handleref_managed);
5195 mono_g_hash_table_destroy (di->tokens);
5196 if (di->generic_def_objects)
5197 mono_g_hash_table_destroy (di->generic_def_objects);
5198 if (di->blob_cache) {
5199 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5200 g_hash_table_destroy (di->blob_cache);
5202 if (di->standalonesig_cache)
5203 g_hash_table_destroy (di->standalonesig_cache);
5204 for (list = di->array_methods; list; list = list->next) {
5205 ArrayMethod *am = (ArrayMethod *)list->data;
5210 g_list_free (di->array_methods);
5211 if (di->gen_params) {
5212 for (i = 0; i < di->gen_params->len; i++) {
5213 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5214 mono_gc_deregister_root ((char*) &entry->gparam);
5217 g_ptr_array_free (di->gen_params, TRUE);
5219 if (di->token_fixups)
5220 mono_g_hash_table_destroy (di->token_fixups);
5221 if (di->method_to_table_idx)
5222 g_hash_table_destroy (di->method_to_table_idx);
5223 if (di->field_to_table_idx)
5224 g_hash_table_destroy (di->field_to_table_idx);
5225 if (di->method_aux_hash)
5226 g_hash_table_destroy (di->method_aux_hash);
5227 if (di->vararg_aux_hash)
5228 g_hash_table_destroy (di->vararg_aux_hash);
5229 g_free (di->strong_name);
5230 g_free (di->win32_res);
5232 g_free (di->public_key);
5234 /*g_print ("string heap destroy for image %p\n", di);*/
5235 mono_dynamic_stream_reset (&di->sheap);
5236 mono_dynamic_stream_reset (&di->code);
5237 mono_dynamic_stream_reset (&di->resources);
5238 mono_dynamic_stream_reset (&di->us);
5239 mono_dynamic_stream_reset (&di->blob);
5240 mono_dynamic_stream_reset (&di->tstream);
5241 mono_dynamic_stream_reset (&di->guid);
5242 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5243 g_free (di->tables [i].values);
5247 #ifndef DISABLE_REFLECTION_EMIT
5250 * mono_image_basic_init:
5251 * @assembly: an assembly builder object
5253 * Create the MonoImage that represents the assembly builder and setup some
5254 * of the helper hash table and the basic metadata streams.
5257 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5259 MonoDynamicAssembly *assembly;
5260 MonoDynamicImage *image;
5261 MonoDomain *domain = mono_object_domain (assemblyb);
5263 MONO_ARCH_SAVE_REGS;
5265 if (assemblyb->dynamic_assembly)
5269 /* assembly->assembly.image might be GC allocated */
5270 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5272 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5275 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5277 assembly->assembly.ref_count = 1;
5278 assembly->assembly.dynamic = TRUE;
5279 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5280 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5281 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5282 if (assemblyb->culture)
5283 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5285 assembly->assembly.aname.culture = g_strdup ("");
5287 if (assemblyb->version) {
5288 char *vstr = mono_string_to_utf8 (assemblyb->version);
5289 char **version = g_strsplit (vstr, ".", 4);
5290 char **parts = version;
5291 assembly->assembly.aname.major = atoi (*parts++);
5292 assembly->assembly.aname.minor = atoi (*parts++);
5293 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5294 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5296 g_strfreev (version);
5299 assembly->assembly.aname.major = 0;
5300 assembly->assembly.aname.minor = 0;
5301 assembly->assembly.aname.build = 0;
5302 assembly->assembly.aname.revision = 0;
5305 assembly->run = assemblyb->access != 2;
5306 assembly->save = assemblyb->access != 1;
5307 assembly->domain = domain;
5309 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5310 image->initial_image = TRUE;
5311 assembly->assembly.aname.name = image->image.name;
5312 assembly->assembly.image = &image->image;
5313 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5314 /* -1 to correct for the trailing NULL byte */
5315 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5316 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5318 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5321 mono_domain_assemblies_lock (domain);
5322 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5323 mono_domain_assemblies_unlock (domain);
5325 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5327 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5329 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5332 #endif /* !DISABLE_REFLECTION_EMIT */
5334 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5337 calc_section_size (MonoDynamicImage *assembly)
5341 /* alignment constraints */
5342 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5343 g_assert ((assembly->code.index % 4) == 0);
5344 assembly->meta_size += 3;
5345 assembly->meta_size &= ~3;
5346 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5347 g_assert ((assembly->resources.index % 4) == 0);
5349 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5350 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5353 if (assembly->win32_res) {
5354 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5356 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5357 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5361 assembly->sections [MONO_SECTION_RELOC].size = 12;
5362 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5372 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5376 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5378 ResTreeNode *t1 = (ResTreeNode*)a;
5379 ResTreeNode *t2 = (ResTreeNode*)b;
5381 return t1->id - t2->id;
5385 * resource_tree_create:
5387 * Organize the resources into a resource tree.
5389 static ResTreeNode *
5390 resource_tree_create (MonoArray *win32_resources)
5392 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5396 tree = g_new0 (ResTreeNode, 1);
5398 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5399 MonoReflectionWin32Resource *win32_res =
5400 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5404 /* FIXME: BUG: this stores managed references in unmanaged memory */
5405 lang_node = g_new0 (ResTreeNode, 1);
5406 lang_node->id = win32_res->lang_id;
5407 lang_node->win32_res = win32_res;
5409 /* Create type node if neccesary */
5411 for (l = tree->children; l; l = l->next)
5412 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5413 type_node = (ResTreeNode*)l->data;
5418 type_node = g_new0 (ResTreeNode, 1);
5419 type_node->id = win32_res->res_type;
5422 * The resource types have to be sorted otherwise
5423 * Windows Explorer can't display the version information.
5425 tree->children = g_slist_insert_sorted (tree->children,
5426 type_node, resource_tree_compare_by_id);
5429 /* Create res node if neccesary */
5431 for (l = type_node->children; l; l = l->next)
5432 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5433 res_node = (ResTreeNode*)l->data;
5438 res_node = g_new0 (ResTreeNode, 1);
5439 res_node->id = win32_res->res_id;
5440 type_node->children = g_slist_append (type_node->children, res_node);
5443 res_node->children = g_slist_append (res_node->children, lang_node);
5450 * resource_tree_encode:
5452 * Encode the resource tree into the format used in the PE file.
5455 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5458 MonoPEResourceDir dir;
5459 MonoPEResourceDirEntry dir_entry;
5460 MonoPEResourceDataEntry data_entry;
5462 guint32 res_id_entries;
5465 * For the format of the resource directory, see the article
5466 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5470 memset (&dir, 0, sizeof (dir));
5471 memset (&dir_entry, 0, sizeof (dir_entry));
5472 memset (&data_entry, 0, sizeof (data_entry));
5474 g_assert (sizeof (dir) == 16);
5475 g_assert (sizeof (dir_entry) == 8);
5476 g_assert (sizeof (data_entry) == 16);
5478 node->offset = p - begin;
5480 /* IMAGE_RESOURCE_DIRECTORY */
5481 res_id_entries = g_slist_length (node->children);
5482 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5484 memcpy (p, &dir, sizeof (dir));
5487 /* Reserve space for entries */
5489 p += sizeof (dir_entry) * res_id_entries;
5491 /* Write children */
5492 for (l = node->children; l; l = l->next) {
5493 ResTreeNode *child = (ResTreeNode*)l->data;
5495 if (child->win32_res) {
5498 child->offset = p - begin;
5500 /* IMAGE_RESOURCE_DATA_ENTRY */
5501 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5502 size = mono_array_length (child->win32_res->res_data);
5503 data_entry.rde_size = GUINT32_TO_LE (size);
5505 memcpy (p, &data_entry, sizeof (data_entry));
5506 p += sizeof (data_entry);
5508 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5511 resource_tree_encode (child, begin, p, &p);
5515 /* IMAGE_RESOURCE_ENTRY */
5516 for (l = node->children; l; l = l->next) {
5517 ResTreeNode *child = (ResTreeNode*)l->data;
5519 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5520 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5522 memcpy (entries, &dir_entry, sizeof (dir_entry));
5523 entries += sizeof (dir_entry);
5530 resource_tree_free (ResTreeNode * node)
5533 for (list = node->children; list; list = list->next)
5534 resource_tree_free ((ResTreeNode*)list->data);
5535 g_slist_free(node->children);
5540 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5545 MonoReflectionWin32Resource *win32_res;
5548 if (!assemblyb->win32_resources)
5552 * Resources are stored in a three level tree inside the PE file.
5553 * - level one contains a node for each type of resource
5554 * - level two contains a node for each resource
5555 * - level three contains a node for each instance of a resource for a
5556 * specific language.
5559 tree = resource_tree_create (assemblyb->win32_resources);
5561 /* Estimate the size of the encoded tree */
5563 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5564 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5565 size += mono_array_length (win32_res->res_data);
5567 /* Directory structure */
5568 size += mono_array_length (assemblyb->win32_resources) * 256;
5569 p = buf = g_malloc (size);
5571 resource_tree_encode (tree, p, p, &p);
5573 g_assert (p - buf <= size);
5575 assembly->win32_res = g_malloc (p - buf);
5576 assembly->win32_res_size = p - buf;
5577 memcpy (assembly->win32_res, buf, p - buf);
5580 resource_tree_free (tree);
5584 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5586 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5589 p += sizeof (MonoPEResourceDir);
5590 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5591 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5592 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5593 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5594 fixup_resource_directory (res_section, child, rva);
5596 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5597 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5600 p += sizeof (MonoPEResourceDirEntry);
5605 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5608 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5609 g_error ("WriteFile returned %d\n", GetLastError ());
5613 * mono_image_create_pefile:
5614 * @mb: a module builder object
5616 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5617 * assembly->pefile where it can be easily retrieved later in chunks.
5620 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5622 MonoMSDOSHeader *msdos;
5623 MonoDotNetHeader *header;
5624 MonoSectionTable *section;
5625 MonoCLIHeader *cli_header;
5626 guint32 size, image_size, virtual_base, text_offset;
5627 guint32 header_start, section_start, file_offset, virtual_offset;
5628 MonoDynamicImage *assembly;
5629 MonoReflectionAssemblyBuilder *assemblyb;
5630 MonoDynamicStream pefile_stream = {0};
5631 MonoDynamicStream *pefile = &pefile_stream;
5633 guint32 *rva, value;
5635 static const unsigned char msheader[] = {
5636 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5637 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5640 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5641 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5642 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5643 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5646 assemblyb = mb->assemblyb;
5648 mono_image_basic_init (assemblyb);
5649 assembly = mb->dynamic_image;
5651 assembly->pe_kind = assemblyb->pe_kind;
5652 assembly->machine = assemblyb->machine;
5653 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5654 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5656 mono_image_build_metadata (mb);
5658 if (mb->is_main && assemblyb->resources) {
5659 int len = mono_array_length (assemblyb->resources);
5660 for (i = 0; i < len; ++i)
5661 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5664 if (mb->resources) {
5665 int len = mono_array_length (mb->resources);
5666 for (i = 0; i < len; ++i)
5667 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5670 build_compressed_metadata (assembly);
5673 assembly_add_win32_resources (assembly, assemblyb);
5675 nsections = calc_section_size (assembly);
5677 /* The DOS header and stub */
5678 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5679 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5681 /* the dotnet header */
5682 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5684 /* the section tables */
5685 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5687 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5688 virtual_offset = VIRT_ALIGN;
5691 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5692 if (!assembly->sections [i].size)
5695 file_offset += FILE_ALIGN - 1;
5696 file_offset &= ~(FILE_ALIGN - 1);
5697 virtual_offset += VIRT_ALIGN - 1;
5698 virtual_offset &= ~(VIRT_ALIGN - 1);
5700 assembly->sections [i].offset = file_offset;
5701 assembly->sections [i].rva = virtual_offset;
5703 file_offset += assembly->sections [i].size;
5704 virtual_offset += assembly->sections [i].size;
5705 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5708 file_offset += FILE_ALIGN - 1;
5709 file_offset &= ~(FILE_ALIGN - 1);
5711 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5713 /* back-patch info */
5714 msdos = (MonoMSDOSHeader*)pefile->data;
5715 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5717 header = (MonoDotNetHeader*)(pefile->data + header_start);
5718 header->pesig [0] = 'P';
5719 header->pesig [1] = 'E';
5721 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5722 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5723 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5724 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5725 if (assemblyb->pekind == 1) {
5727 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5730 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5733 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5735 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5736 header->pe.pe_major = 6;
5737 header->pe.pe_minor = 0;
5738 size = assembly->sections [MONO_SECTION_TEXT].size;
5739 size += FILE_ALIGN - 1;
5740 size &= ~(FILE_ALIGN - 1);
5741 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5742 size = assembly->sections [MONO_SECTION_RSRC].size;
5743 size += FILE_ALIGN - 1;
5744 size &= ~(FILE_ALIGN - 1);
5745 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5746 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5747 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5748 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5749 /* pe_rva_entry_point always at the beginning of the text section */
5750 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5752 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5753 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5754 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5755 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5756 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5757 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5758 size = section_start;
5759 size += FILE_ALIGN - 1;
5760 size &= ~(FILE_ALIGN - 1);
5761 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5763 size += VIRT_ALIGN - 1;
5764 size &= ~(VIRT_ALIGN - 1);
5765 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5768 // Translate the PEFileKind value to the value expected by the Windows loader
5774 // PEFileKinds.Dll == 1
5775 // PEFileKinds.ConsoleApplication == 2
5776 // PEFileKinds.WindowApplication == 3
5779 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5780 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5782 if (assemblyb->pekind == 3)
5787 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5789 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5790 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5791 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5792 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5793 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5794 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5796 /* fill data directory entries */
5798 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5799 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5801 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5802 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5804 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5805 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5806 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5807 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5808 /* patch entrypoint name */
5809 if (assemblyb->pekind == 1)
5810 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5812 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5813 /* patch imported function RVA name */
5814 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5815 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5817 /* the import table */
5818 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5819 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5820 /* patch imported dll RVA name and other entries in the dir */
5821 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5822 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5823 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5824 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5825 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5826 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5828 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5829 value = (assembly->text_rva + assembly->imp_names_offset);
5830 *p++ = (value) & 0xff;
5831 *p++ = (value >> 8) & (0xff);
5832 *p++ = (value >> 16) & (0xff);
5833 *p++ = (value >> 24) & (0xff);
5835 /* the CLI header info */
5836 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5837 cli_header->ch_size = GUINT32_FROM_LE (72);
5838 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5839 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5840 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5841 if (assemblyb->entry_point) {
5842 guint32 table_idx = 0;
5843 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5844 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5845 table_idx = methodb->table_idx;
5847 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5849 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5851 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5853 /* The embedded managed resources */
5854 text_offset = assembly->text_rva + assembly->code.index;
5855 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5856 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5857 text_offset += assembly->resources.index;
5858 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5859 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5860 text_offset += assembly->meta_size;
5861 if (assembly->strong_name_size) {
5862 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5863 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5864 text_offset += assembly->strong_name_size;
5867 /* write the section tables and section content */
5868 section = (MonoSectionTable*)(pefile->data + section_start);
5869 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5870 static const char section_names [][7] = {
5871 ".text", ".rsrc", ".reloc"
5873 if (!assembly->sections [i].size)
5875 strcpy (section->st_name, section_names [i]);
5876 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5877 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5878 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5879 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5880 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5881 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5882 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5886 checked_write_file (file, pefile->data, pefile->index);
5888 mono_dynamic_stream_reset (pefile);
5890 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5891 if (!assembly->sections [i].size)
5894 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5895 g_error ("SetFilePointer returned %d\n", GetLastError ());
5898 case MONO_SECTION_TEXT:
5899 /* patch entry point */
5900 p = (guchar*)(assembly->code.data + 2);
5901 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5902 *p++ = (value) & 0xff;
5903 *p++ = (value >> 8) & 0xff;
5904 *p++ = (value >> 16) & 0xff;
5905 *p++ = (value >> 24) & 0xff;
5907 checked_write_file (file, assembly->code.data, assembly->code.index);
5908 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5909 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5910 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5913 g_free (assembly->image.raw_metadata);
5915 case MONO_SECTION_RELOC: {
5919 guint16 type_and_offset;
5923 g_assert (sizeof (reloc) == 12);
5925 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5926 reloc.block_size = GUINT32_FROM_LE (12);
5929 * the entrypoint is always at the start of the text section
5930 * 3 is IMAGE_REL_BASED_HIGHLOW
5931 * 2 is patch_size_rva - text_rva
5933 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5936 checked_write_file (file, &reloc, sizeof (reloc));
5940 case MONO_SECTION_RSRC:
5941 if (assembly->win32_res) {
5943 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5944 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5945 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5949 g_assert_not_reached ();
5953 /* check that the file is properly padded */
5954 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5955 g_error ("SetFilePointer returned %d\n", GetLastError ());
5956 if (! SetEndOfFile (file))
5957 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5959 mono_dynamic_stream_reset (&assembly->code);
5960 mono_dynamic_stream_reset (&assembly->us);
5961 mono_dynamic_stream_reset (&assembly->blob);
5962 mono_dynamic_stream_reset (&assembly->guid);
5963 mono_dynamic_stream_reset (&assembly->sheap);
5965 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5966 g_hash_table_destroy (assembly->blob_cache);
5967 assembly->blob_cache = NULL;
5970 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5973 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5975 g_assert_not_reached ();
5978 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5980 #ifndef DISABLE_REFLECTION_EMIT
5982 MonoReflectionModule *
5983 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5987 MonoImageOpenStatus status;
5988 MonoDynamicAssembly *assembly;
5989 guint32 module_count;
5990 MonoImage **new_modules;
5991 gboolean *new_modules_loaded;
5993 name = mono_string_to_utf8 (fileName);
5995 image = mono_image_open (name, &status);
5998 if (status == MONO_IMAGE_ERROR_ERRNO)
5999 exc = mono_get_exception_file_not_found (fileName);
6001 exc = mono_get_exception_bad_image_format (name);
6003 mono_raise_exception (exc);
6008 assembly = ab->dynamic_assembly;
6009 image->assembly = (MonoAssembly*)assembly;
6011 module_count = image->assembly->image->module_count;
6012 new_modules = g_new0 (MonoImage *, module_count + 1);
6013 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6015 if (image->assembly->image->modules)
6016 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6017 if (image->assembly->image->modules_loaded)
6018 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6019 new_modules [module_count] = image;
6020 new_modules_loaded [module_count] = TRUE;
6021 mono_image_addref (image);
6023 g_free (image->assembly->image->modules);
6024 image->assembly->image->modules = new_modules;
6025 image->assembly->image->modules_loaded = new_modules_loaded;
6026 image->assembly->image->module_count ++;
6028 mono_assembly_load_references (image, &status);
6030 mono_image_close (image);
6031 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6034 return mono_module_get_object (mono_domain_get (), image);
6037 #endif /* DISABLE_REFLECTION_EMIT */
6040 * We need to return always the same object for MethodInfo, FieldInfo etc..
6041 * but we need to consider the reflected type.
6042 * type uses a different hash, since it uses custom hash/equal functions.
6047 MonoClass *refclass;
6051 reflected_equal (gconstpointer a, gconstpointer b) {
6052 const ReflectedEntry *ea = a;
6053 const ReflectedEntry *eb = b;
6055 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6059 reflected_hash (gconstpointer a) {
6060 const ReflectedEntry *ea = a;
6061 return mono_aligned_addr_hash (ea->item);
6064 #define CHECK_OBJECT(t,p,k) \
6070 mono_domain_lock (domain); \
6071 if (!domain->refobject_hash) \
6072 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6073 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6074 mono_domain_unlock (domain); \
6077 mono_domain_unlock (domain); \
6080 #ifdef HAVE_BOEHM_GC
6081 /* ReflectedEntry doesn't need to be GC tracked */
6082 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6083 #define FREE_REFENTRY(entry) g_free ((entry))
6084 #define REFENTRY_REQUIRES_CLEANUP
6086 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6088 #define FREE_REFENTRY(entry)
6091 #define CACHE_OBJECT(t,p,o,k) \
6094 ReflectedEntry pe; \
6096 pe.refclass = (k); \
6097 mono_domain_lock (domain); \
6098 if (!domain->refobject_hash) \
6099 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6100 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6102 ReflectedEntry *e = ALLOC_REFENTRY; \
6104 e->refclass = (k); \
6105 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6108 mono_domain_unlock (domain); \
6113 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6115 mono_domain_lock (domain);
6116 if (domain->refobject_hash) {
6118 gpointer orig_pe, orig_value;
6121 pe.refclass = klass;
6122 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6123 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6124 FREE_REFENTRY (orig_pe);
6127 mono_domain_unlock (domain);
6130 #ifdef REFENTRY_REQUIRES_CLEANUP
6132 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6134 FREE_REFENTRY (key);
6139 mono_reflection_cleanup_domain (MonoDomain *domain)
6141 if (domain->refobject_hash) {
6142 /*let's avoid scanning the whole hashtable if not needed*/
6143 #ifdef REFENTRY_REQUIRES_CLEANUP
6144 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6146 mono_g_hash_table_destroy (domain->refobject_hash);
6147 domain->refobject_hash = NULL;
6151 #ifndef DISABLE_REFLECTION_EMIT
6153 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6155 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6159 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6161 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6165 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6167 MonoDynamicImage *image = moduleb->dynamic_image;
6168 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6172 MonoImage **new_modules;
6174 char *name, *fqname;
6176 * FIXME: we already created an image in mono_image_basic_init (), but
6177 * we don't know which module it belongs to, since that is only
6178 * determined at assembly save time.
6180 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6181 name = mono_string_to_utf8 (ab->name);
6182 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6183 if (!mono_error_ok (&error)) {
6185 mono_error_raise_exception (&error);
6187 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6189 moduleb->module.image = &image->image;
6190 moduleb->dynamic_image = image;
6191 register_module (mono_object_domain (moduleb), moduleb, image);
6193 /* register the module with the assembly */
6194 ass = ab->dynamic_assembly->assembly.image;
6195 module_count = ass->module_count;
6196 new_modules = g_new0 (MonoImage *, module_count + 1);
6199 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6200 new_modules [module_count] = &image->image;
6201 mono_image_addref (&image->image);
6203 g_free (ass->modules);
6204 ass->modules = new_modules;
6205 ass->module_count ++;
6210 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6212 MonoDynamicImage *image = moduleb->dynamic_image;
6214 g_assert (type->type);
6215 image->wrappers_type = mono_class_from_mono_type (type->type);
6221 * mono_assembly_get_object:
6222 * @domain: an app domain
6223 * @assembly: an assembly
6225 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6227 MonoReflectionAssembly*
6228 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6230 static MonoClass *assembly_type;
6231 MonoReflectionAssembly *res;
6233 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6234 if (!assembly_type) {
6235 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6237 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6239 assembly_type = class;
6241 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6242 res->assembly = assembly;
6244 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6249 MonoReflectionModule*
6250 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6252 static MonoClass *module_type;
6253 MonoReflectionModule *res;
6256 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6258 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6260 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6262 module_type = class;
6264 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6267 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6269 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6270 basename = g_path_get_basename (image->name);
6271 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6272 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6276 if (image->assembly->image == image) {
6277 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6281 if (image->assembly->image->modules) {
6282 for (i = 0; i < image->assembly->image->module_count; i++) {
6283 if (image->assembly->image->modules [i] == image)
6284 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6286 g_assert (res->token);
6290 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6293 MonoReflectionModule*
6294 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6296 static MonoClass *module_type;
6297 MonoReflectionModule *res;
6298 MonoTableInfo *table;
6299 guint32 cols [MONO_FILE_SIZE];
6301 guint32 i, name_idx;
6305 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6307 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6309 module_type = class;
6311 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6313 table = &image->tables [MONO_TABLE_FILE];
6314 g_assert (table_index < table->rows);
6315 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6318 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6319 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6321 /* Check whenever the row has a corresponding row in the moduleref table */
6322 table = &image->tables [MONO_TABLE_MODULEREF];
6323 for (i = 0; i < table->rows; ++i) {
6324 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6325 val = mono_metadata_string_heap (image, name_idx);
6326 if (strcmp (val, name) == 0)
6327 res->image = image->modules [i];
6330 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6331 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6332 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6333 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6334 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6340 verify_safe_for_managed_space (MonoType *type)
6342 switch (type->type) {
6344 case MONO_TYPE_ARRAY:
6345 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6347 return verify_safe_for_managed_space (type->data.type);
6348 case MONO_TYPE_SZARRAY:
6349 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6350 case MONO_TYPE_GENERICINST: {
6351 MonoGenericInst *inst = type->data.generic_class->inst;
6355 for (i = 0; i < inst->type_argc; ++i)
6356 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6362 case MONO_TYPE_MVAR:
6369 mono_type_normalize (MonoType *type)
6372 MonoGenericClass *gclass;
6373 MonoGenericInst *ginst;
6375 MonoGenericContainer *gcontainer;
6376 MonoType **argv = NULL;
6377 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6379 if (type->type != MONO_TYPE_GENERICINST)
6382 gclass = type->data.generic_class;
6383 ginst = gclass->context.class_inst;
6384 if (!ginst->is_open)
6387 gtd = gclass->container_class;
6388 gcontainer = gtd->generic_container;
6389 argv = g_newa (MonoType*, ginst->type_argc);
6391 for (i = 0; i < ginst->type_argc; ++i) {
6392 MonoType *t = ginst->type_argv [i], *norm;
6393 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6394 is_denorm_gtd = FALSE;
6395 norm = mono_type_normalize (t);
6398 requires_rebind = TRUE;
6402 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6404 if (requires_rebind) {
6405 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6406 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6412 * mono_type_get_object:
6413 * @domain: an app domain
6416 * Return an System.MonoType object representing the type @type.
6419 mono_type_get_object (MonoDomain *domain, MonoType *type)
6421 MonoType *norm_type;
6422 MonoReflectionType *res;
6423 MonoClass *klass = mono_class_from_mono_type (type);
6425 /*we must avoid using @type as it might have come
6426 * from a mono_metadata_type_dup and the caller
6427 * expects that is can be freed.
6428 * Using the right type from
6430 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6432 /* void is very common */
6433 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6434 return (MonoReflectionType*)domain->typeof_void;
6437 * If the vtable of the given class was already created, we can use
6438 * the MonoType from there and avoid all locking and hash table lookups.
6440 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6441 * that the resulting object is different.
6443 if (type == &klass->byval_arg && !klass->image->dynamic) {
6444 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6445 if (vtable && vtable->type)
6446 return vtable->type;
6449 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6450 mono_domain_lock (domain);
6451 if (!domain->type_hash)
6452 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6453 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6454 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6455 mono_domain_unlock (domain);
6456 mono_loader_unlock ();
6460 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6461 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6462 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6463 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6464 * artifact of how generics are encoded and should be transparent to managed code so we
6465 * need to weed out this diference when retrieving managed System.Type objects.
6467 norm_type = mono_type_normalize (type);
6468 if (norm_type != type) {
6469 res = mono_type_get_object (domain, norm_type);
6470 mono_g_hash_table_insert (domain->type_hash, type, res);
6471 mono_domain_unlock (domain);
6472 mono_loader_unlock ();
6476 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6477 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6480 if (!verify_safe_for_managed_space (type)) {
6481 mono_domain_unlock (domain);
6482 mono_loader_unlock ();
6483 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6486 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6487 gboolean is_type_done = TRUE;
6488 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6489 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6490 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6492 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6493 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6495 if (gparam->owner && gparam->owner->is_method) {
6496 MonoMethod *method = gparam->owner->owner.method;
6497 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6498 is_type_done = FALSE;
6499 } else if (gparam->owner && !gparam->owner->is_method) {
6500 MonoClass *klass = gparam->owner->owner.klass;
6501 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6502 is_type_done = FALSE;
6506 /* g_assert_not_reached (); */
6507 /* should this be considered an error condition? */
6508 if (is_type_done && !type->byref) {
6509 mono_domain_unlock (domain);
6510 mono_loader_unlock ();
6511 return mono_class_get_ref_info (klass);
6514 /* This is stored in vtables/JITted code so it has to be pinned */
6515 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6517 mono_g_hash_table_insert (domain->type_hash, type, res);
6519 if (type->type == MONO_TYPE_VOID)
6520 domain->typeof_void = (MonoObject*)res;
6522 mono_domain_unlock (domain);
6523 mono_loader_unlock ();
6528 * mono_method_get_object:
6529 * @domain: an app domain
6531 * @refclass: the reflected type (can be NULL)
6533 * Return an System.Reflection.MonoMethod object representing the method @method.
6535 MonoReflectionMethod*
6536 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6539 * We use the same C representation for methods and constructors, but the type
6540 * name in C# is different.
6542 static MonoClass *System_Reflection_MonoMethod = NULL;
6543 static MonoClass *System_Reflection_MonoCMethod = NULL;
6544 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6545 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6547 MonoReflectionMethod *ret;
6549 if (method->is_inflated) {
6550 MonoReflectionGenericMethod *gret;
6552 refclass = method->klass;
6553 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6554 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6555 if (!System_Reflection_MonoGenericCMethod)
6556 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6557 klass = System_Reflection_MonoGenericCMethod;
6559 if (!System_Reflection_MonoGenericMethod)
6560 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6561 klass = System_Reflection_MonoGenericMethod;
6563 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6564 gret->method.method = method;
6565 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6566 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6567 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6571 refclass = method->klass;
6573 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6574 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6575 if (!System_Reflection_MonoCMethod)
6576 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6577 klass = System_Reflection_MonoCMethod;
6580 if (!System_Reflection_MonoMethod)
6581 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6582 klass = System_Reflection_MonoMethod;
6584 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6585 ret->method = method;
6586 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6587 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6591 * mono_method_clear_object:
6593 * Clear the cached reflection objects for the dynamic method METHOD.
6596 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6599 g_assert (method->dynamic);
6601 klass = method->klass;
6603 clear_cached_object (domain, method, klass);
6604 klass = klass->parent;
6606 /* Added by mono_param_get_objects () */
6607 clear_cached_object (domain, &(method->signature), NULL);
6608 klass = method->klass;
6610 clear_cached_object (domain, &(method->signature), klass);
6611 klass = klass->parent;
6616 * mono_field_get_object:
6617 * @domain: an app domain
6621 * Return an System.Reflection.MonoField object representing the field @field
6624 MonoReflectionField*
6625 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6627 MonoReflectionField *res;
6628 static MonoClass *monofield_klass;
6630 CHECK_OBJECT (MonoReflectionField *, field, klass);
6631 if (!monofield_klass)
6632 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6633 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6636 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6638 if (is_field_on_inst (field)) {
6639 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6640 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6643 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6644 res->attrs = mono_field_get_flags (field);
6646 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6650 * mono_property_get_object:
6651 * @domain: an app domain
6653 * @property: a property
6655 * Return an System.Reflection.MonoProperty object representing the property @property
6658 MonoReflectionProperty*
6659 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6661 MonoReflectionProperty *res;
6662 static MonoClass *monoproperty_klass;
6664 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6665 if (!monoproperty_klass)
6666 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6667 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6669 res->property = property;
6670 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6674 * mono_event_get_object:
6675 * @domain: an app domain
6679 * Return an System.Reflection.MonoEvent object representing the event @event
6682 MonoReflectionEvent*
6683 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6685 MonoReflectionEvent *res;
6686 MonoReflectionMonoEvent *mono_event;
6687 static MonoClass *monoevent_klass;
6689 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6690 if (!monoevent_klass)
6691 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6692 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6693 mono_event->klass = klass;
6694 mono_event->event = event;
6695 res = (MonoReflectionEvent*)mono_event;
6696 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6700 * mono_get_reflection_missing_object:
6701 * @domain: Domain where the object lives
6703 * Returns the System.Reflection.Missing.Value singleton object
6704 * (of type System.Reflection.Missing).
6706 * Used as the value for ParameterInfo.DefaultValue when Optional
6710 mono_get_reflection_missing_object (MonoDomain *domain)
6713 static MonoClassField *missing_value_field = NULL;
6715 if (!missing_value_field) {
6716 MonoClass *missing_klass;
6717 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6718 mono_class_init (missing_klass);
6719 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6720 g_assert (missing_value_field);
6722 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6728 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6731 *dbnull = mono_get_dbnull_object (domain);
6736 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6738 if (!*reflection_missing)
6739 *reflection_missing = mono_get_reflection_missing_object (domain);
6740 return *reflection_missing;
6744 * mono_param_get_objects:
6745 * @domain: an app domain
6748 * Return an System.Reflection.ParameterInfo array object representing the parameters
6749 * in the method @method.
6752 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6754 static MonoClass *System_Reflection_ParameterInfo;
6755 static MonoClass *System_Reflection_ParameterInfo_array;
6757 MonoArray *res = NULL;
6758 MonoReflectionMethod *member = NULL;
6759 MonoReflectionParameter *param = NULL;
6760 char **names, **blobs = NULL;
6761 guint32 *types = NULL;
6762 MonoType *type = NULL;
6763 MonoObject *dbnull = NULL;
6764 MonoObject *missing = NULL;
6765 MonoMarshalSpec **mspecs;
6766 MonoMethodSignature *sig;
6767 MonoVTable *pinfo_vtable;
6770 if (!System_Reflection_ParameterInfo_array) {
6773 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6774 mono_memory_barrier ();
6775 System_Reflection_ParameterInfo = klass;
6777 klass = mono_array_class_get (klass, 1);
6778 mono_memory_barrier ();
6779 System_Reflection_ParameterInfo_array = klass;
6782 sig = mono_method_signature_checked (method, &error);
6783 if (!mono_error_ok (&error))
6784 mono_error_raise_exception (&error);
6786 if (!sig->param_count)
6787 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6789 /* Note: the cache is based on the address of the signature into the method
6790 * since we already cache MethodInfos with the method as keys.
6792 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6794 member = mono_method_get_object (domain, method, refclass);
6795 names = g_new (char *, sig->param_count);
6796 mono_method_get_param_names (method, (const char **) names);
6798 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6799 mono_method_get_marshal_info (method, mspecs);
6801 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6802 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6803 for (i = 0; i < sig->param_count; ++i) {
6804 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6805 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6806 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6807 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6808 param->PositionImpl = i;
6809 param->AttrsImpl = sig->params [i]->attrs;
6811 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6812 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6813 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6815 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6819 blobs = g_new0 (char *, sig->param_count);
6820 types = g_new0 (guint32, sig->param_count);
6821 get_default_param_value_blobs (method, blobs, types);
6824 /* Build MonoType for the type from the Constant Table */
6826 type = g_new0 (MonoType, 1);
6827 type->type = types [i];
6828 type->data.klass = NULL;
6829 if (types [i] == MONO_TYPE_CLASS)
6830 type->data.klass = mono_defaults.object_class;
6831 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6832 /* For enums, types [i] contains the base type */
6834 type->type = MONO_TYPE_VALUETYPE;
6835 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6837 type->data.klass = mono_class_from_mono_type (type);
6839 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6841 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6842 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6843 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6844 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6846 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6852 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6854 mono_array_setref (res, i, param);
6861 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6863 mono_metadata_free_marshal_spec (mspecs [i]);
6866 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6870 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6872 return mono_param_get_objects_internal (domain, method, NULL);
6876 * mono_method_body_get_object:
6877 * @domain: an app domain
6880 * Return an System.Reflection.MethodBody object representing the method @method.
6882 MonoReflectionMethodBody*
6883 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6885 static MonoClass *System_Reflection_MethodBody = NULL;
6886 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6887 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6888 MonoReflectionMethodBody *ret;
6889 MonoMethodHeader *header;
6891 guint32 method_rva, local_var_sig_token;
6893 unsigned char format, flags;
6896 /* for compatibility with .net */
6897 if (method->dynamic)
6898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6900 if (!System_Reflection_MethodBody)
6901 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6902 if (!System_Reflection_LocalVariableInfo)
6903 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6904 if (!System_Reflection_ExceptionHandlingClause)
6905 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6907 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6909 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6910 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6911 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6912 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6915 image = method->klass->image;
6916 header = mono_method_get_header (method);
6918 if (!image->dynamic) {
6919 /* Obtain local vars signature token */
6920 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6921 ptr = mono_image_rva_map (image, method_rva);
6922 flags = *(const unsigned char *) ptr;
6923 format = flags & METHOD_HEADER_FORMAT_MASK;
6925 case METHOD_HEADER_TINY_FORMAT:
6926 local_var_sig_token = 0;
6928 case METHOD_HEADER_FAT_FORMAT:
6932 local_var_sig_token = read32 (ptr);
6935 g_assert_not_reached ();
6938 local_var_sig_token = 0; //FIXME
6940 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6942 ret->init_locals = header->init_locals;
6943 ret->max_stack = header->max_stack;
6944 ret->local_var_sig_token = local_var_sig_token;
6945 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6946 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6949 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6950 for (i = 0; i < header->num_locals; ++i) {
6951 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6952 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6953 info->is_pinned = header->locals [i]->pinned;
6954 info->local_index = i;
6955 mono_array_setref (ret->locals, i, info);
6959 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6960 for (i = 0; i < header->num_clauses; ++i) {
6961 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6962 MonoExceptionClause *clause = &header->clauses [i];
6964 info->flags = clause->flags;
6965 info->try_offset = clause->try_offset;
6966 info->try_length = clause->try_len;
6967 info->handler_offset = clause->handler_offset;
6968 info->handler_length = clause->handler_len;
6969 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6970 info->filter_offset = clause->data.filter_offset;
6971 else if (clause->data.catch_class)
6972 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6974 mono_array_setref (ret->clauses, i, info);
6977 mono_metadata_free_mh (header);
6978 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6983 * mono_get_dbnull_object:
6984 * @domain: Domain where the object lives
6986 * Returns the System.DBNull.Value singleton object
6988 * Used as the value for ParameterInfo.DefaultValue
6991 mono_get_dbnull_object (MonoDomain *domain)
6994 static MonoClassField *dbnull_value_field = NULL;
6996 if (!dbnull_value_field) {
6997 MonoClass *dbnull_klass;
6998 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6999 mono_class_init (dbnull_klass);
7000 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7001 g_assert (dbnull_value_field);
7003 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7009 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7011 guint32 param_index, i, lastp, crow = 0;
7012 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7015 MonoClass *klass = method->klass;
7016 MonoImage *image = klass->image;
7017 MonoMethodSignature *methodsig = mono_method_signature (method);
7019 MonoTableInfo *constt;
7020 MonoTableInfo *methodt;
7021 MonoTableInfo *paramt;
7023 if (!methodsig->param_count)
7026 mono_class_init (klass);
7028 if (klass->image->dynamic) {
7029 MonoReflectionMethodAux *aux;
7030 if (method->is_inflated)
7031 method = ((MonoMethodInflated*)method)->declaring;
7032 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7033 if (aux && aux->param_defaults) {
7034 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7035 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7040 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7041 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7042 constt = &image->tables [MONO_TABLE_CONSTANT];
7044 idx = mono_method_get_index (method) - 1;
7045 g_assert (idx != -1);
7047 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7048 if (idx + 1 < methodt->rows)
7049 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7051 lastp = paramt->rows + 1;
7053 for (i = param_index; i < lastp; ++i) {
7056 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7057 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7059 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7062 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7067 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7068 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7069 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7076 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7081 MonoType *basetype = type;
7086 klass = mono_class_from_mono_type (type);
7087 if (klass->valuetype) {
7088 object = mono_object_new (domain, klass);
7089 retval = ((gchar *) object + sizeof (MonoObject));
7090 if (klass->enumtype)
7091 basetype = mono_class_enum_basetype (klass);
7096 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7103 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7106 gboolean quoted = FALSE;
7108 memset (assembly, 0, sizeof (MonoAssemblyName));
7109 assembly->culture = "";
7110 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7117 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7128 /* Remove trailing whitespace */
7130 while (*s && g_ascii_isspace (*s))
7133 while (g_ascii_isspace (*p))
7136 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7138 assembly->major = strtoul (p, &s, 10);
7139 if (s == p || *s != '.')
7142 assembly->minor = strtoul (p, &s, 10);
7143 if (s == p || *s != '.')
7146 assembly->build = strtoul (p, &s, 10);
7147 if (s == p || *s != '.')
7150 assembly->revision = strtoul (p, &s, 10);
7154 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7156 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7157 assembly->culture = "";
7160 assembly->culture = p;
7161 while (*p && *p != ',') {
7165 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7167 if (strncmp (p, "null", 4) == 0) {
7172 while (*p && *p != ',') {
7175 len = (p - start + 1);
7176 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7177 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7178 g_strlcpy ((char*)assembly->public_key_token, start, len);
7181 while (*p && *p != ',')
7185 while (g_ascii_isspace (*p) || *p == ',') {
7199 * mono_reflection_parse_type:
7202 * Parse a type name as accepted by the GetType () method and output the info
7203 * extracted in the info structure.
7204 * the name param will be mangled, so, make a copy before passing it to this function.
7205 * The fields in info will be valid until the memory pointed to by name is valid.
7207 * See also mono_type_get_name () below.
7209 * Returns: 0 on parse error.
7212 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7213 MonoTypeNameParse *info)
7215 char *start, *p, *w, *temp, *last_point, *startn;
7216 int in_modifiers = 0;
7217 int isbyref = 0, rank, arity = 0, i;
7219 start = p = w = name;
7221 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7222 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7223 info->name = info->name_space = NULL;
7224 info->nested = NULL;
7225 info->modifiers = NULL;
7226 info->type_arguments = NULL;
7228 /* last_point separates the namespace from the name */
7231 while (*p == ' ') p++, start++, w++, name++;
7236 *p = 0; /* NULL terminate the name */
7238 info->nested = g_list_append (info->nested, startn);
7239 /* we have parsed the nesting namespace + name */
7243 info->name_space = start;
7245 info->name = last_point + 1;
7247 info->name_space = (char *)"";
7266 i = strtol (p, &temp, 10);
7283 info->name_space = start;
7285 info->name = last_point + 1;
7287 info->name_space = (char *)"";
7294 if (isbyref) /* only one level allowed by the spec */
7297 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7301 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7307 info->type_arguments = g_ptr_array_new ();
7308 for (i = 0; i < arity; i++) {
7309 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7310 gboolean fqname = FALSE;
7312 g_ptr_array_add (info->type_arguments, subinfo);
7319 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7322 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7323 if (fqname && (*p != ']')) {
7331 while (*p && (*p != ']'))
7339 if (g_ascii_isspace (*aname)) {
7346 !assembly_name_to_aname (&subinfo->assembly, aname))
7348 } else if (fqname && (*p == ']')) {
7352 if (i + 1 < arity) {
7372 else if (*p == '*') /* '*' means unknown lower bound */
7373 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7380 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7391 if (g_ascii_isspace (*p)) {
7398 return 0; /* missing assembly name */
7399 if (!assembly_name_to_aname (&info->assembly, p))
7405 if (info->assembly.name)
7408 // *w = 0; /* terminate class name */
7410 if (!info->name || !*info->name)
7414 /* add other consistency checks */
7419 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7421 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7425 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7427 gboolean type_resolve = FALSE;
7429 MonoImage *rootimage = image;
7431 if (info->assembly.name) {
7432 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7433 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7435 * This could happen in the AOT compiler case when the search hook is not
7438 assembly = image->assembly;
7440 /* then we must load the assembly ourselve - see #60439 */
7441 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7445 image = assembly->image;
7446 } else if (!image) {
7447 image = mono_defaults.corlib;
7450 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7451 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7452 image = mono_defaults.corlib;
7453 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7460 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7465 gboolean bounded = FALSE;
7468 image = mono_defaults.corlib;
7471 klass = mono_class_from_name_case (image, info->name_space, info->name);
7473 klass = mono_class_from_name (image, info->name_space, info->name);
7476 for (mod = info->nested; mod; mod = mod->next) {
7477 gpointer iter = NULL;
7481 mono_class_init (parent);
7483 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7485 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7488 if (strcmp (klass->name, mod->data) == 0)
7498 if (info->type_arguments) {
7499 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7500 MonoReflectionType *the_type;
7504 for (i = 0; i < info->type_arguments->len; i++) {
7505 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7507 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7508 if (!type_args [i]) {
7514 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7516 instance = mono_reflection_bind_generic_parameters (
7517 the_type, info->type_arguments->len, type_args);
7523 klass = mono_class_from_mono_type (instance);
7526 for (mod = info->modifiers; mod; mod = mod->next) {
7527 modval = GPOINTER_TO_UINT (mod->data);
7528 if (!modval) { /* byref: must be last modifier */
7529 return &klass->this_arg;
7530 } else if (modval == -1) {
7531 klass = mono_ptr_class_get (&klass->byval_arg);
7532 } else if (modval == -2) {
7534 } else { /* array rank */
7535 klass = mono_bounded_array_class_get (klass, modval, bounded);
7539 return &klass->byval_arg;
7543 * mono_reflection_get_type:
7544 * @image: a metadata context
7545 * @info: type description structure
7546 * @ignorecase: flag for case-insensitive string compares
7547 * @type_resolve: whenever type resolve was already tried
7549 * Build a MonoType from the type description in @info.
7554 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7555 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7559 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7561 MonoReflectionAssemblyBuilder *abuilder;
7565 g_assert (assembly->dynamic);
7566 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7568 /* Enumerate all modules */
7571 if (abuilder->modules) {
7572 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7573 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7574 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7580 if (!type && abuilder->loaded_modules) {
7581 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7582 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7583 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7593 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7596 MonoReflectionAssembly *assembly;
7600 if (image && image->dynamic)
7601 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7603 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7606 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7613 *type_resolve = TRUE;
7616 /* Reconstruct the type name */
7617 fullName = g_string_new ("");
7618 if (info->name_space && (info->name_space [0] != '\0'))
7619 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7621 g_string_printf (fullName, "%s", info->name);
7622 for (mod = info->nested; mod; mod = mod->next)
7623 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7625 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7627 if (assembly->assembly->dynamic)
7628 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7630 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7633 g_string_free (fullName, TRUE);
7638 mono_reflection_free_type_info (MonoTypeNameParse *info)
7640 g_list_free (info->modifiers);
7641 g_list_free (info->nested);
7643 if (info->type_arguments) {
7646 for (i = 0; i < info->type_arguments->len; i++) {
7647 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7649 mono_reflection_free_type_info (subinfo);
7650 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7654 g_ptr_array_free (info->type_arguments, TRUE);
7659 * mono_reflection_type_from_name:
7661 * @image: a metadata context (can be NULL).
7663 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7664 * it defaults to get the type from @image or, if @image is NULL or loading
7665 * from it fails, uses corlib.
7669 mono_reflection_type_from_name (char *name, MonoImage *image)
7671 MonoType *type = NULL;
7672 MonoTypeNameParse info;
7675 /* Make a copy since parse_type modifies its argument */
7676 tmp = g_strdup (name);
7678 /*g_print ("requested type %s\n", str);*/
7679 if (mono_reflection_parse_type (tmp, &info)) {
7680 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7684 mono_reflection_free_type_info (&info);
7689 * mono_reflection_get_token:
7691 * Return the metadata token of OBJ which should be an object
7692 * representing a metadata element.
7695 mono_reflection_get_token (MonoObject *obj)
7700 klass = obj->vtable->klass;
7702 if (strcmp (klass->name, "MethodBuilder") == 0) {
7703 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7705 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7706 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7707 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7709 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7710 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7711 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7713 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7714 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7715 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7716 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7717 } else if (strcmp (klass->name, "MonoType") == 0) {
7718 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7719 MonoClass *mc = mono_class_from_mono_type (type);
7720 if (!mono_class_init (mc))
7721 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7723 token = mc->type_token;
7724 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7725 strcmp (klass->name, "MonoMethod") == 0 ||
7726 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7727 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7728 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7729 if (m->method->is_inflated) {
7730 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7731 return inflated->declaring->token;
7733 token = m->method->token;
7735 } else if (strcmp (klass->name, "MonoField") == 0) {
7736 MonoReflectionField *f = (MonoReflectionField*)obj;
7738 if (is_field_on_inst (f->field)) {
7739 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7740 int field_index = f->field - dgclass->fields;
7743 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7744 obj = dgclass->field_objects [field_index];
7745 return mono_reflection_get_token (obj);
7747 token = mono_class_get_field_token (f->field);
7748 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7749 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7751 token = mono_class_get_property_token (p->property);
7752 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7753 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7755 token = mono_class_get_event_token (p->event);
7756 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7757 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7758 MonoClass *member_class = mono_object_class (p->MemberImpl);
7759 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7761 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7762 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7763 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7766 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7767 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7769 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7770 MonoException *ex = mono_get_exception_not_implemented (msg);
7772 mono_raise_exception (ex);
7779 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7781 int slen, type = t->type;
7782 MonoClass *tklass = t->data.klass;
7788 case MONO_TYPE_BOOLEAN: {
7789 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7794 case MONO_TYPE_CHAR:
7796 case MONO_TYPE_I2: {
7797 guint16 *val = g_malloc (sizeof (guint16));
7802 #if SIZEOF_VOID_P == 4
7808 case MONO_TYPE_I4: {
7809 guint32 *val = g_malloc (sizeof (guint32));
7814 #if SIZEOF_VOID_P == 8
7815 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7819 case MONO_TYPE_I8: {
7820 guint64 *val = g_malloc (sizeof (guint64));
7825 case MONO_TYPE_R8: {
7826 double *val = g_malloc (sizeof (double));
7831 case MONO_TYPE_VALUETYPE:
7832 if (t->data.klass->enumtype) {
7833 type = mono_class_enum_basetype (t->data.klass)->type;
7836 MonoClass *k = t->data.klass;
7838 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7839 guint64 *val = g_malloc (sizeof (guint64));
7845 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7848 case MONO_TYPE_STRING:
7849 if (*p == (char)0xFF) {
7853 slen = mono_metadata_decode_value (p, &p);
7855 return mono_string_new_len (mono_domain_get (), p, slen);
7856 case MONO_TYPE_CLASS: {
7859 if (*p == (char)0xFF) {
7864 slen = mono_metadata_decode_value (p, &p);
7865 n = g_memdup (p, slen + 1);
7867 t = mono_reflection_type_from_name (n, image);
7869 g_warning ("Cannot load type '%s'", n);
7873 return mono_type_get_object (mono_domain_get (), t);
7877 case MONO_TYPE_OBJECT: {
7880 MonoClass *subc = NULL;
7885 } else if (subt == 0x0E) {
7886 type = MONO_TYPE_STRING;
7888 } else if (subt == 0x1D) {
7889 MonoType simple_type = {{0}};
7893 type = MONO_TYPE_SZARRAY;
7894 if (etype == 0x50) {
7895 tklass = mono_defaults.systemtype_class;
7898 /* See Partition II, Appendix B3 */
7899 etype = MONO_TYPE_OBJECT;
7900 simple_type.type = etype;
7901 tklass = mono_class_from_mono_type (&simple_type);
7904 } else if (subt == 0x55) {
7907 slen = mono_metadata_decode_value (p, &p);
7908 n = g_memdup (p, slen + 1);
7910 t = mono_reflection_type_from_name (n, image);
7912 g_error ("Cannot load type '%s'", n);
7915 subc = mono_class_from_mono_type (t);
7916 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7917 MonoType simple_type = {{0}};
7918 simple_type.type = subt;
7919 subc = mono_class_from_mono_type (&simple_type);
7921 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7923 val = load_cattr_value (image, &subc->byval_arg, p, end);
7924 obj = mono_object_new (mono_domain_get (), subc);
7925 g_assert (!subc->has_references);
7926 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7930 case MONO_TYPE_SZARRAY: {
7932 guint32 i, alen, basetype;
7935 if (alen == 0xffffffff) {
7939 arr = mono_array_new (mono_domain_get(), tklass, alen);
7940 basetype = tklass->byval_arg.type;
7941 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7942 basetype = mono_class_enum_basetype (tklass)->type;
7947 case MONO_TYPE_BOOLEAN:
7948 for (i = 0; i < alen; i++) {
7949 MonoBoolean val = *p++;
7950 mono_array_set (arr, MonoBoolean, i, val);
7953 case MONO_TYPE_CHAR:
7956 for (i = 0; i < alen; i++) {
7957 guint16 val = read16 (p);
7958 mono_array_set (arr, guint16, i, val);
7965 for (i = 0; i < alen; i++) {
7966 guint32 val = read32 (p);
7967 mono_array_set (arr, guint32, i, val);
7972 for (i = 0; i < alen; i++) {
7975 mono_array_set (arr, double, i, val);
7981 for (i = 0; i < alen; i++) {
7982 guint64 val = read64 (p);
7983 mono_array_set (arr, guint64, i, val);
7987 case MONO_TYPE_CLASS:
7988 case MONO_TYPE_OBJECT:
7989 case MONO_TYPE_STRING:
7990 for (i = 0; i < alen; i++) {
7991 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7992 mono_array_setref (arr, i, item);
7996 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8002 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8008 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8010 static MonoClass *klass;
8011 static MonoMethod *ctor;
8013 void *params [2], *unboxed;
8016 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8018 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8020 params [0] = mono_type_get_object (mono_domain_get (), t);
8022 retval = mono_object_new (mono_domain_get (), klass);
8023 unboxed = mono_object_unbox (retval);
8024 mono_runtime_invoke (ctor, unboxed, params, NULL);
8030 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8032 static MonoClass *klass;
8033 static MonoMethod *ctor;
8035 void *unboxed, *params [2];
8038 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8040 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8043 params [1] = typedarg;
8044 retval = mono_object_new (mono_domain_get (), klass);
8045 unboxed = mono_object_unbox (retval);
8046 mono_runtime_invoke (ctor, unboxed, params, NULL);
8052 type_is_reference (MonoType *type)
8054 switch (type->type) {
8055 case MONO_TYPE_BOOLEAN:
8056 case MONO_TYPE_CHAR:
8069 case MONO_TYPE_VALUETYPE:
8077 free_param_data (MonoMethodSignature *sig, void **params) {
8079 for (i = 0; i < sig->param_count; ++i) {
8080 if (!type_is_reference (sig->params [i]))
8081 g_free (params [i]);
8086 * Find the field index in the metadata FieldDef table.
8089 find_field_index (MonoClass *klass, MonoClassField *field) {
8092 for (i = 0; i < klass->field.count; ++i) {
8093 if (field == &klass->fields [i])
8094 return klass->field.first + 1 + i;
8100 * Find the property index in the metadata Property table.
8103 find_property_index (MonoClass *klass, MonoProperty *property) {
8106 for (i = 0; i < klass->ext->property.count; ++i) {
8107 if (property == &klass->ext->properties [i])
8108 return klass->ext->property.first + 1 + i;
8114 * Find the event index in the metadata Event table.
8117 find_event_index (MonoClass *klass, MonoEvent *event) {
8120 for (i = 0; i < klass->ext->event.count; ++i) {
8121 if (event == &klass->ext->events [i])
8122 return klass->ext->event.first + 1 + i;
8128 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8130 const char *p = (const char*)data;
8132 guint32 i, j, num_named;
8134 void *params_buf [32];
8136 MonoMethodSignature *sig;
8138 mono_error_init (error);
8140 mono_class_init (method->klass);
8142 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8143 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8148 attr = mono_object_new (mono_domain_get (), method->klass);
8149 mono_runtime_invoke (method, attr, NULL, NULL);
8153 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8156 /*g_print ("got attr %s\n", method->klass->name);*/
8158 sig = mono_method_signature (method);
8159 if (sig->param_count < 32)
8160 params = params_buf;
8162 /* Allocate using GC so it gets GC tracking */
8163 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8167 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8168 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8172 attr = mono_object_new (mono_domain_get (), method->klass);
8173 mono_runtime_invoke (method, attr, params, NULL);
8174 free_param_data (method->signature, params);
8175 num_named = read16 (named);
8177 for (j = 0; j < num_named; j++) {
8179 char *name, named_type, data_type;
8180 named_type = *named++;
8181 data_type = *named++; /* type of data */
8182 if (data_type == MONO_TYPE_SZARRAY)
8183 data_type = *named++;
8184 if (data_type == MONO_TYPE_ENUM) {
8187 type_len = mono_metadata_decode_blob_size (named, &named);
8188 type_name = g_malloc (type_len + 1);
8189 memcpy (type_name, named, type_len);
8190 type_name [type_len] = 0;
8192 /* FIXME: lookup the type and check type consistency */
8195 name_len = mono_metadata_decode_blob_size (named, &named);
8196 name = g_malloc (name_len + 1);
8197 memcpy (name, named, name_len);
8198 name [name_len] = 0;
8200 if (named_type == 0x53) {
8201 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8202 void *val = load_cattr_value (image, field->type, named, &named);
8203 mono_field_set_value (attr, field, val);
8204 if (!type_is_reference (field->type))
8206 } else if (named_type == 0x54) {
8209 MonoType *prop_type;
8211 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8212 /* can we have more that 1 arg in a custom attr named property? */
8213 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8214 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8215 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8216 mono_property_set_value (prop, attr, pparams, NULL);
8217 if (!type_is_reference (prop_type))
8218 g_free (pparams [0]);
8223 if (params != params_buf)
8224 mono_gc_free_fixed (params);
8230 * mono_reflection_create_custom_attr_data_args:
8232 * Create an array of typed and named arguments from the cattr blob given by DATA.
8233 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8234 * NAMED_ARG_INFO will contain information about the named arguments.
8237 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)
8239 MonoArray *typedargs, *namedargs;
8240 MonoClass *attrklass;
8242 const char *p = (const char*)data;
8244 guint32 i, j, num_named;
8245 CattrNamedArg *arginfo = NULL;
8247 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8250 mono_class_init (method->klass);
8254 *named_arg_info = NULL;
8256 domain = mono_domain_get ();
8258 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8261 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8265 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8269 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8270 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8271 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8272 mono_array_setref (typedargs, i, obj);
8274 if (!type_is_reference (mono_method_signature (method)->params [i]))
8279 num_named = read16 (named);
8280 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8282 attrklass = method->klass;
8284 arginfo = g_new0 (CattrNamedArg, num_named);
8285 *named_arg_info = arginfo;
8287 for (j = 0; j < num_named; j++) {
8289 char *name, named_type, data_type;
8290 named_type = *named++;
8291 data_type = *named++; /* type of data */
8292 if (data_type == MONO_TYPE_SZARRAY)
8293 data_type = *named++;
8294 if (data_type == MONO_TYPE_ENUM) {
8297 type_len = mono_metadata_decode_blob_size (named, &named);
8298 type_name = g_malloc (type_len + 1);
8299 memcpy (type_name, named, type_len);
8300 type_name [type_len] = 0;
8302 /* FIXME: lookup the type and check type consistency */
8305 name_len = mono_metadata_decode_blob_size (named, &named);
8306 name = g_malloc (name_len + 1);
8307 memcpy (name, named, name_len);
8308 name [name_len] = 0;
8310 if (named_type == 0x53) {
8312 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8315 arginfo [j].type = field->type;
8316 arginfo [j].field = field;
8318 val = load_cattr_value (image, field->type, named, &named);
8319 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8320 mono_array_setref (namedargs, j, obj);
8321 if (!type_is_reference (field->type))
8323 } else if (named_type == 0x54) {
8325 MonoType *prop_type;
8326 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8329 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8330 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8332 arginfo [j].type = prop_type;
8333 arginfo [j].prop = prop;
8335 val = load_cattr_value (image, prop_type, named, &named);
8336 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8337 mono_array_setref (namedargs, j, obj);
8338 if (!type_is_reference (prop_type))
8344 *typed_args = typedargs;
8345 *named_args = namedargs;
8349 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8352 MonoArray *typedargs, *namedargs;
8355 CattrNamedArg *arginfo;
8364 image = assembly->assembly->image;
8365 method = ref_method->method;
8366 domain = mono_object_domain (ref_method);
8368 if (!mono_class_init (method->klass))
8369 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8371 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8372 if (mono_loader_get_last_error ())
8373 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8375 if (!typedargs || !namedargs)
8378 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8379 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8380 MonoObject *typedarg;
8382 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8383 mono_array_setref (typedargs, i, typedarg);
8386 for (i = 0; i < mono_array_length (namedargs); ++i) {
8387 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8388 MonoObject *typedarg, *namedarg, *minfo;
8390 if (arginfo [i].prop)
8391 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8393 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8395 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8396 namedarg = create_cattr_named_arg (minfo, typedarg);
8398 mono_array_setref (namedargs, i, namedarg);
8401 *ctor_args = typedargs;
8402 *named_args = namedargs;
8406 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8408 static MonoMethod *ctor;
8413 g_assert (image->assembly);
8416 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8418 domain = mono_domain_get ();
8419 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8420 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8421 params [1] = mono_assembly_get_object (domain, image->assembly);
8422 params [2] = (gpointer)&cattr->data;
8423 params [3] = &cattr->data_size;
8424 mono_runtime_invoke (ctor, attr, params, NULL);
8429 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8435 mono_error_init (error);
8438 for (i = 0; i < cinfo->num_attrs; ++i) {
8439 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8443 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8445 for (i = 0; i < cinfo->num_attrs; ++i) {
8446 if (!cinfo->attrs [i].ctor)
8447 /* The cattr type is not finished yet */
8448 /* We should include the type name but cinfo doesn't contain it */
8449 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8450 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8451 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8452 if (!mono_error_ok (error))
8454 mono_array_setref (result, n, attr);
8462 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8466 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8470 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8476 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8477 for (i = 0; i < cinfo->num_attrs; ++i) {
8478 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8479 mono_array_setref (result, i, attr);
8485 * mono_custom_attrs_from_index:
8487 * Returns: NULL if no attributes are found or if a loading error occurs.
8490 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8492 guint32 mtoken, i, len;
8493 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8495 MonoCustomAttrInfo *ainfo;
8496 GList *tmp, *list = NULL;
8499 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8501 i = mono_metadata_custom_attrs_from_index (image, idx);
8505 while (i < ca->rows) {
8506 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8508 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8511 len = g_list_length (list);
8514 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8515 ainfo->num_attrs = len;
8516 ainfo->image = image;
8517 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8518 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8519 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8520 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8521 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8522 mtoken |= MONO_TOKEN_METHOD_DEF;
8524 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8525 mtoken |= MONO_TOKEN_MEMBER_REF;
8528 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8531 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8532 if (!ainfo->attrs [i].ctor) {
8533 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8539 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8540 /*FIXME raising an exception here doesn't make any sense*/
8541 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8546 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8547 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8548 ainfo->attrs [i].data = (guchar*)data;
8556 mono_custom_attrs_from_method (MonoMethod *method)
8561 * An instantiated method has the same cattrs as the generic method definition.
8563 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8564 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8566 if (method->is_inflated)
8567 method = ((MonoMethodInflated *) method)->declaring;
8569 if (method->dynamic || method->klass->image->dynamic)
8570 return lookup_custom_attr (method->klass->image, method);
8573 /* Synthetic methods */
8576 idx = mono_method_get_index (method);
8577 idx <<= MONO_CUSTOM_ATTR_BITS;
8578 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8579 return mono_custom_attrs_from_index (method->klass->image, idx);
8583 mono_custom_attrs_from_class (MonoClass *klass)
8587 if (klass->generic_class)
8588 klass = klass->generic_class->container_class;
8590 if (klass->image->dynamic)
8591 return lookup_custom_attr (klass->image, klass);
8593 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8594 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8595 idx <<= MONO_CUSTOM_ATTR_BITS;
8596 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8598 idx = mono_metadata_token_index (klass->type_token);
8599 idx <<= MONO_CUSTOM_ATTR_BITS;
8600 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8602 return mono_custom_attrs_from_index (klass->image, idx);
8606 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8610 if (assembly->image->dynamic)
8611 return lookup_custom_attr (assembly->image, assembly);
8612 idx = 1; /* there is only one assembly */
8613 idx <<= MONO_CUSTOM_ATTR_BITS;
8614 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8615 return mono_custom_attrs_from_index (assembly->image, idx);
8618 static MonoCustomAttrInfo*
8619 mono_custom_attrs_from_module (MonoImage *image)
8624 return lookup_custom_attr (image, image);
8625 idx = 1; /* there is only one module */
8626 idx <<= MONO_CUSTOM_ATTR_BITS;
8627 idx |= MONO_CUSTOM_ATTR_MODULE;
8628 return mono_custom_attrs_from_index (image, idx);
8632 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8636 if (klass->image->dynamic) {
8637 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8638 return lookup_custom_attr (klass->image, property);
8640 idx = find_property_index (klass, property);
8641 idx <<= MONO_CUSTOM_ATTR_BITS;
8642 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8643 return mono_custom_attrs_from_index (klass->image, idx);
8647 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8651 if (klass->image->dynamic) {
8652 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8653 return lookup_custom_attr (klass->image, event);
8655 idx = find_event_index (klass, event);
8656 idx <<= MONO_CUSTOM_ATTR_BITS;
8657 idx |= MONO_CUSTOM_ATTR_EVENT;
8658 return mono_custom_attrs_from_index (klass->image, idx);
8662 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8665 if (klass->image->dynamic) {
8666 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8667 return lookup_custom_attr (klass->image, field);
8669 idx = find_field_index (klass, field);
8670 idx <<= MONO_CUSTOM_ATTR_BITS;
8671 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8672 return mono_custom_attrs_from_index (klass->image, idx);
8676 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8679 guint32 i, idx, method_index;
8680 guint32 param_list, param_last, param_pos, found;
8682 MonoReflectionMethodAux *aux;
8685 * An instantiated method has the same cattrs as the generic method definition.
8687 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8688 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8690 if (method->is_inflated)
8691 method = ((MonoMethodInflated *) method)->declaring;
8693 if (method->klass->image->dynamic) {
8694 MonoCustomAttrInfo *res, *ainfo;
8697 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8698 if (!aux || !aux->param_cattr)
8701 /* Need to copy since it will be freed later */
8702 ainfo = aux->param_cattr [param];
8705 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8706 res = g_malloc0 (size);
8707 memcpy (res, ainfo, size);
8711 image = method->klass->image;
8712 method_index = mono_method_get_index (method);
8715 ca = &image->tables [MONO_TABLE_METHOD];
8717 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8718 if (method_index == ca->rows) {
8719 ca = &image->tables [MONO_TABLE_PARAM];
8720 param_last = ca->rows + 1;
8722 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8723 ca = &image->tables [MONO_TABLE_PARAM];
8726 for (i = param_list; i < param_last; ++i) {
8727 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8728 if (param_pos == param) {
8736 idx <<= MONO_CUSTOM_ATTR_BITS;
8737 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8738 return mono_custom_attrs_from_index (image, idx);
8742 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8746 for (i = 0; i < ainfo->num_attrs; ++i) {
8747 klass = ainfo->attrs [i].ctor->klass;
8748 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8755 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8762 for (i = 0; i < ainfo->num_attrs; ++i) {
8763 klass = ainfo->attrs [i].ctor->klass;
8764 if (mono_class_has_parent (klass, attr_klass)) {
8769 if (attr_index == -1)
8772 attrs = mono_custom_attrs_construct (ainfo);
8774 return mono_array_get (attrs, MonoObject*, attr_index);
8780 * mono_reflection_get_custom_attrs_info:
8781 * @obj: a reflection object handle
8783 * Return the custom attribute info for attributes defined for the
8784 * reflection handle @obj. The objects.
8786 * FIXME this function leaks like a sieve for SRE objects.
8789 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8792 MonoCustomAttrInfo *cinfo = NULL;
8794 klass = obj->vtable->klass;
8795 if (klass == mono_defaults.monotype_class) {
8796 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8797 klass = mono_class_from_mono_type (type);
8798 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8799 cinfo = mono_custom_attrs_from_class (klass);
8800 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8801 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8802 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8803 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8804 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8805 cinfo = mono_custom_attrs_from_module (module->image);
8806 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8807 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8808 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8809 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8810 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8811 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8812 } else if (strcmp ("MonoField", klass->name) == 0) {
8813 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8814 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8815 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8816 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8817 cinfo = mono_custom_attrs_from_method (rmethod->method);
8818 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8819 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8820 cinfo = mono_custom_attrs_from_method (rmethod->method);
8821 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8822 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8823 MonoClass *member_class = mono_object_class (param->MemberImpl);
8824 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8825 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8826 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8827 } else if (is_sr_mono_property (member_class)) {
8828 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8830 if (!(method = prop->property->get))
8831 method = prop->property->set;
8834 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8836 #ifndef DISABLE_REFLECTION_EMIT
8837 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8838 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8839 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8840 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8841 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8842 MonoMethod *method = NULL;
8843 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8844 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8845 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8846 method = ((MonoReflectionMethod *)c->cb)->method;
8848 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));
8850 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8854 char *type_name = mono_type_get_full_name (member_class);
8855 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8856 MonoException *ex = mono_get_exception_not_supported (msg);
8859 mono_raise_exception (ex);
8861 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8862 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8863 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8864 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8865 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8866 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8867 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8868 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8869 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8870 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8871 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8872 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8873 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8874 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8875 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8876 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8877 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8878 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8879 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8880 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8881 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8882 } else { /* handle other types here... */
8883 g_error ("get custom attrs not yet supported for %s", klass->name);
8890 * mono_reflection_get_custom_attrs_by_type:
8891 * @obj: a reflection object handle
8893 * Return an array with all the custom attributes defined of the
8894 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8895 * of that type are returned. The objects are fully build. Return NULL if a loading error
8899 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8902 MonoCustomAttrInfo *cinfo;
8904 mono_error_init (error);
8906 cinfo = mono_reflection_get_custom_attrs_info (obj);
8908 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8910 mono_custom_attrs_free (cinfo);
8912 if (mono_loader_get_last_error ())
8914 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8921 * mono_reflection_get_custom_attrs:
8922 * @obj: a reflection object handle
8924 * Return an array with all the custom attributes defined of the
8925 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8929 mono_reflection_get_custom_attrs (MonoObject *obj)
8933 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8937 * mono_reflection_get_custom_attrs_data:
8938 * @obj: a reflection obj handle
8940 * Returns an array of System.Reflection.CustomAttributeData,
8941 * which include information about attributes reflected on
8942 * types loaded using the Reflection Only methods
8945 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8948 MonoCustomAttrInfo *cinfo;
8950 cinfo = mono_reflection_get_custom_attrs_info (obj);
8952 result = mono_custom_attrs_data_construct (cinfo);
8954 mono_custom_attrs_free (cinfo);
8956 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8961 static MonoReflectionType*
8962 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8964 static MonoMethod *method_get_underlying_system_type = NULL;
8965 MonoMethod *usertype_method;
8967 if (!method_get_underlying_system_type)
8968 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8969 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8970 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8975 is_corlib_type (MonoClass *class)
8977 return class->image == mono_defaults.corlib;
8980 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8981 static MonoClass *cached_class; \
8983 return cached_class == _class; \
8984 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8985 cached_class = _class; \
8992 #ifndef DISABLE_REFLECTION_EMIT
8994 is_sre_array (MonoClass *class)
8996 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9000 is_sre_byref (MonoClass *class)
9002 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9006 is_sre_pointer (MonoClass *class)
9008 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9012 is_sre_generic_instance (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9018 is_sre_type_builder (MonoClass *class)
9020 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9024 is_sre_method_builder (MonoClass *class)
9026 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9030 is_sre_ctor_builder (MonoClass *class)
9032 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9036 is_sre_field_builder (MonoClass *class)
9038 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9042 is_sre_method_on_tb_inst (MonoClass *class)
9044 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9048 is_sre_ctor_on_tb_inst (MonoClass *class)
9050 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9054 mono_reflection_type_get_handle (MonoReflectionType* ref)
9062 if (is_usertype (ref)) {
9063 ref = mono_reflection_type_get_underlying_system_type (ref);
9064 if (ref == NULL || is_usertype (ref))
9070 class = mono_object_class (ref);
9072 if (is_sre_array (class)) {
9074 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9075 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9077 if (sre_array->rank == 0) //single dimentional array
9078 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9080 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9081 sre_array->type.type = res;
9083 } else if (is_sre_byref (class)) {
9085 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9086 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9088 res = &mono_class_from_mono_type (base)->this_arg;
9089 sre_byref->type.type = res;
9091 } else if (is_sre_pointer (class)) {
9093 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9094 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9096 res = &mono_ptr_class_get (base)->byval_arg;
9097 sre_pointer->type.type = res;
9099 } else if (is_sre_generic_instance (class)) {
9100 MonoType *res, **types;
9101 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9104 count = mono_array_length (gclass->type_arguments);
9105 types = g_new0 (MonoType*, count);
9106 for (i = 0; i < count; ++i) {
9107 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9108 types [i] = mono_reflection_type_get_handle (t);
9115 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9118 gclass->type.type = res;
9122 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9129 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9131 mono_reflection_type_get_handle (type);
9135 mono_reflection_register_with_runtime (MonoReflectionType *type)
9137 MonoType *res = mono_reflection_type_get_handle (type);
9138 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9142 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9144 class = mono_class_from_mono_type (res);
9146 mono_loader_lock (); /*same locking as mono_type_get_object*/
9147 mono_domain_lock (domain);
9149 if (!class->image->dynamic) {
9150 mono_class_setup_supertypes (class);
9152 if (!domain->type_hash)
9153 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9154 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9155 mono_g_hash_table_insert (domain->type_hash, res, type);
9157 mono_domain_unlock (domain);
9158 mono_loader_unlock ();
9162 * LOCKING: Assumes the loader lock is held.
9164 static MonoMethodSignature*
9165 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9166 MonoMethodSignature *sig;
9169 count = parameters? mono_array_length (parameters): 0;
9171 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9172 sig->param_count = count;
9173 sig->sentinelpos = -1; /* FIXME */
9174 for (i = 0; i < count; ++i)
9175 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9180 * LOCKING: Assumes the loader lock is held.
9182 static MonoMethodSignature*
9183 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9184 MonoMethodSignature *sig;
9186 sig = parameters_to_signature (image, ctor->parameters);
9187 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9188 sig->ret = &mono_defaults.void_class->byval_arg;
9193 * LOCKING: Assumes the loader lock is held.
9195 static MonoMethodSignature*
9196 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9197 MonoMethodSignature *sig;
9199 sig = parameters_to_signature (image, method->parameters);
9200 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9201 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9202 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9206 static MonoMethodSignature*
9207 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9208 MonoMethodSignature *sig;
9210 sig = parameters_to_signature (NULL, method->parameters);
9211 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9212 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9213 sig->generic_param_count = 0;
9218 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9220 MonoClass *klass = mono_object_class (prop);
9221 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9222 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9223 *name = mono_string_to_utf8 (pb->name);
9224 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9226 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9227 *name = g_strdup (p->property->name);
9228 if (p->property->get)
9229 *type = mono_method_signature (p->property->get)->ret;
9231 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9236 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9238 MonoClass *klass = mono_object_class (field);
9239 if (strcmp (klass->name, "FieldBuilder") == 0) {
9240 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9241 *name = mono_string_to_utf8 (fb->name);
9242 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9244 MonoReflectionField *f = (MonoReflectionField *)field;
9245 *name = g_strdup (mono_field_get_name (f->field));
9246 *type = f->field->type;
9250 #else /* DISABLE_REFLECTION_EMIT */
9253 mono_reflection_register_with_runtime (MonoReflectionType *type)
9259 is_sre_type_builder (MonoClass *class)
9265 is_sre_generic_instance (MonoClass *class)
9271 init_type_builder_generics (MonoObject *type)
9275 #endif /* !DISABLE_REFLECTION_EMIT */
9279 is_sr_mono_field (MonoClass *class)
9281 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9285 is_sr_mono_property (MonoClass *class)
9287 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9291 is_sr_mono_method (MonoClass *class)
9293 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9297 is_sr_mono_cmethod (MonoClass *class)
9299 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9303 is_sr_mono_generic_method (MonoClass *class)
9305 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9309 is_sr_mono_generic_cmethod (MonoClass *class)
9311 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9315 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9317 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9321 is_usertype (MonoReflectionType *ref)
9323 MonoClass *class = mono_object_class (ref);
9324 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9327 static MonoReflectionType*
9328 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9330 if (!type || type->type)
9333 if (is_usertype (type)) {
9334 type = mono_reflection_type_get_underlying_system_type (type);
9335 if (is_usertype (type))
9336 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9342 * Encode a value in a custom attribute stream of bytes.
9343 * The value to encode is either supplied as an object in argument val
9344 * (valuetypes are boxed), or as a pointer to the data in the
9346 * @type represents the type of the value
9347 * @buffer is the start of the buffer
9348 * @p the current position in the buffer
9349 * @buflen contains the size of the buffer and is used to return the new buffer size
9350 * if this needs to be realloced.
9351 * @retbuffer and @retp return the start and the position of the buffer
9354 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9356 MonoTypeEnum simple_type;
9358 if ((p-buffer) + 10 >= *buflen) {
9361 newbuf = g_realloc (buffer, *buflen);
9362 p = newbuf + (p-buffer);
9366 argval = ((char*)arg + sizeof (MonoObject));
9367 simple_type = type->type;
9369 switch (simple_type) {
9370 case MONO_TYPE_BOOLEAN:
9375 case MONO_TYPE_CHAR:
9378 swap_with_size (p, argval, 2, 1);
9384 swap_with_size (p, argval, 4, 1);
9388 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9398 swap_with_size (p, argval, 8, 1);
9404 swap_with_size (p, argval, 8, 1);
9407 case MONO_TYPE_VALUETYPE:
9408 if (type->data.klass->enumtype) {
9409 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9412 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9415 case MONO_TYPE_STRING: {
9422 str = mono_string_to_utf8 ((MonoString*)arg);
9423 slen = strlen (str);
9424 if ((p-buffer) + 10 + slen >= *buflen) {
9428 newbuf = g_realloc (buffer, *buflen);
9429 p = newbuf + (p-buffer);
9432 mono_metadata_encode_value (slen, p, &p);
9433 memcpy (p, str, slen);
9438 case MONO_TYPE_CLASS: {
9446 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9447 slen = strlen (str);
9448 if ((p-buffer) + 10 + slen >= *buflen) {
9452 newbuf = g_realloc (buffer, *buflen);
9453 p = newbuf + (p-buffer);
9456 mono_metadata_encode_value (slen, p, &p);
9457 memcpy (p, str, slen);
9462 case MONO_TYPE_SZARRAY: {
9464 MonoClass *eclass, *arg_eclass;
9467 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9470 len = mono_array_length ((MonoArray*)arg);
9472 *p++ = (len >> 8) & 0xff;
9473 *p++ = (len >> 16) & 0xff;
9474 *p++ = (len >> 24) & 0xff;
9476 *retbuffer = buffer;
9477 eclass = type->data.klass;
9478 arg_eclass = mono_object_class (arg)->element_class;
9481 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9482 eclass = mono_defaults.object_class;
9484 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9485 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9486 int elsize = mono_class_array_element_size (arg_eclass);
9487 for (i = 0; i < len; ++i) {
9488 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9491 } else if (eclass->valuetype && arg_eclass->valuetype) {
9492 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9493 int elsize = mono_class_array_element_size (eclass);
9494 for (i = 0; i < len; ++i) {
9495 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9499 for (i = 0; i < len; ++i) {
9500 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9505 case MONO_TYPE_OBJECT: {
9511 * The parameter type is 'object' but the type of the actual
9512 * argument is not. So we have to add type information to the blob
9513 * too. This is completely undocumented in the spec.
9517 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9522 klass = mono_object_class (arg);
9524 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9527 } else if (klass->enumtype) {
9529 } else if (klass == mono_defaults.string_class) {
9530 simple_type = MONO_TYPE_STRING;
9533 } else if (klass->rank == 1) {
9535 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9536 /* See Partition II, Appendix B3 */
9539 *p++ = klass->element_class->byval_arg.type;
9540 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9542 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9543 *p++ = simple_type = klass->byval_arg.type;
9546 g_error ("unhandled type in custom attr");
9548 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9549 slen = strlen (str);
9550 if ((p-buffer) + 10 + slen >= *buflen) {
9554 newbuf = g_realloc (buffer, *buflen);
9555 p = newbuf + (p-buffer);
9558 mono_metadata_encode_value (slen, p, &p);
9559 memcpy (p, str, slen);
9562 simple_type = mono_class_enum_basetype (klass)->type;
9566 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9569 *retbuffer = buffer;
9573 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9575 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9576 char *str = type_get_qualified_name (type, NULL);
9577 int slen = strlen (str);
9581 * This seems to be optional...
9584 mono_metadata_encode_value (slen, p, &p);
9585 memcpy (p, str, slen);
9588 } else if (type->type == MONO_TYPE_OBJECT) {
9590 } else if (type->type == MONO_TYPE_CLASS) {
9591 /* it should be a type: encode_cattr_value () has the check */
9594 mono_metadata_encode_value (type->type, p, &p);
9595 if (type->type == MONO_TYPE_SZARRAY)
9596 /* See the examples in Partition VI, Annex B */
9597 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9603 #ifndef DISABLE_REFLECTION_EMIT
9605 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9608 /* Preallocate a large enough buffer */
9609 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9610 char *str = type_get_qualified_name (type, NULL);
9613 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9614 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9620 len += strlen (name);
9622 if ((p-buffer) + 20 + len >= *buflen) {
9626 newbuf = g_realloc (buffer, *buflen);
9627 p = newbuf + (p-buffer);
9631 encode_field_or_prop_type (type, p, &p);
9633 len = strlen (name);
9634 mono_metadata_encode_value (len, p, &p);
9635 memcpy (p, name, len);
9637 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9639 *retbuffer = buffer;
9643 * mono_reflection_get_custom_attrs_blob:
9644 * @ctor: custom attribute constructor
9645 * @ctorArgs: arguments o the constructor
9651 * Creates the blob of data that needs to be saved in the metadata and that represents
9652 * the custom attributed described by @ctor, @ctorArgs etc.
9653 * Returns: a Byte array representing the blob of data.
9656 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9659 MonoMethodSignature *sig;
9664 MONO_ARCH_SAVE_REGS;
9666 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9667 /* sig is freed later so allocate it in the heap */
9668 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9670 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9673 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9675 p = buffer = g_malloc (buflen);
9676 /* write the prolog */
9679 for (i = 0; i < sig->param_count; ++i) {
9680 arg = mono_array_get (ctorArgs, MonoObject*, i);
9681 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9685 i += mono_array_length (properties);
9687 i += mono_array_length (fields);
9689 *p++ = (i >> 8) & 0xff;
9692 for (i = 0; i < mono_array_length (properties); ++i) {
9696 prop = mono_array_get (properties, gpointer, i);
9697 get_prop_name_and_type (prop, &pname, &ptype);
9698 *p++ = 0x54; /* PROPERTY signature */
9699 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9706 for (i = 0; i < mono_array_length (fields); ++i) {
9710 field = mono_array_get (fields, gpointer, i);
9711 get_field_name_and_type (field, &fname, &ftype);
9712 *p++ = 0x53; /* FIELD signature */
9713 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9718 g_assert (p - buffer <= buflen);
9719 buflen = p - buffer;
9720 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9721 p = mono_array_addr (result, char, 0);
9722 memcpy (p, buffer, buflen);
9724 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9730 * mono_reflection_setup_internal_class:
9731 * @tb: a TypeBuilder object
9733 * Creates a MonoClass that represents the TypeBuilder.
9734 * This is a trick that lets us simplify a lot of reflection code
9735 * (and will allow us to support Build and Run assemblies easier).
9738 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9741 MonoClass *klass, *parent;
9743 MONO_ARCH_SAVE_REGS;
9745 RESOLVE_TYPE (tb->parent);
9747 mono_loader_lock ();
9750 /* check so we can compile corlib correctly */
9751 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9752 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9753 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9755 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9761 /* the type has already being created: it means we just have to change the parent */
9762 if (tb->type.type) {
9763 klass = mono_class_from_mono_type (tb->type.type);
9764 klass->parent = NULL;
9765 /* fool mono_class_setup_parent */
9766 klass->supertypes = NULL;
9767 mono_class_setup_parent (klass, parent);
9768 mono_class_setup_mono_type (klass);
9769 mono_loader_unlock ();
9773 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9775 klass->image = &tb->module->dynamic_image->image;
9777 klass->inited = 1; /* we lie to the runtime */
9778 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9779 if (!mono_error_ok (&error))
9781 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9782 if (!mono_error_ok (&error))
9784 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9785 klass->flags = tb->attrs;
9787 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9789 klass->element_class = klass;
9791 if (mono_class_get_ref_info (klass) == NULL) {
9793 mono_class_set_ref_info (klass, tb);
9795 /* Put into cache so mono_class_get () will find it.
9796 Skip nested types as those should not be available on the global scope. */
9797 if (!tb->nesting_type) {
9798 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9800 klass->image->reflection_info_unregister_classes =
9801 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9804 g_assert (mono_class_get_ref_info (klass) == tb);
9807 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9808 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9810 if (parent != NULL) {
9811 mono_class_setup_parent (klass, parent);
9812 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9813 const char *old_n = klass->name;
9814 /* trick to get relative numbering right when compiling corlib */
9815 klass->name = "BuildingObject";
9816 mono_class_setup_parent (klass, mono_defaults.object_class);
9817 klass->name = old_n;
9820 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9821 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9822 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9823 klass->instance_size = sizeof (MonoObject);
9824 klass->size_inited = 1;
9825 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9828 mono_class_setup_mono_type (klass);
9830 mono_class_setup_supertypes (klass);
9833 * FIXME: handle interfaces.
9836 tb->type.type = &klass->byval_arg;
9838 if (tb->nesting_type) {
9839 g_assert (tb->nesting_type->type);
9840 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9843 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9845 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9847 mono_loader_unlock ();
9851 mono_loader_unlock ();
9852 mono_error_raise_exception (&error);
9856 * mono_reflection_setup_generic_class:
9857 * @tb: a TypeBuilder object
9859 * Setup the generic class before adding the first generic parameter.
9862 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9867 * mono_reflection_create_generic_class:
9868 * @tb: a TypeBuilder object
9870 * Creates the generic class after all generic parameters have been added.
9873 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9878 MONO_ARCH_SAVE_REGS;
9880 klass = mono_class_from_mono_type (tb->type.type);
9882 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9884 if (klass->generic_container || (count == 0))
9887 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9889 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9891 klass->generic_container->owner.klass = klass;
9892 klass->generic_container->type_argc = count;
9893 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9895 klass->is_generic = 1;
9897 for (i = 0; i < count; i++) {
9898 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9899 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9900 klass->generic_container->type_params [i] = *param;
9901 /*Make sure we are a diferent type instance */
9902 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9903 klass->generic_container->type_params [i].info.pklass = NULL;
9904 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9906 g_assert (klass->generic_container->type_params [i].param.owner);
9909 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9913 * mono_reflection_create_internal_class:
9914 * @tb: a TypeBuilder object
9916 * Actually create the MonoClass that is associated with the TypeBuilder.
9919 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9923 MONO_ARCH_SAVE_REGS;
9925 klass = mono_class_from_mono_type (tb->type.type);
9927 mono_loader_lock ();
9928 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9929 MonoReflectionFieldBuilder *fb;
9931 MonoType *enum_basetype;
9933 g_assert (tb->fields != NULL);
9934 g_assert (mono_array_length (tb->fields) >= 1);
9936 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9938 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9939 mono_loader_unlock ();
9943 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9944 klass->element_class = mono_class_from_mono_type (enum_basetype);
9945 if (!klass->element_class)
9946 klass->element_class = mono_class_from_mono_type (enum_basetype);
9949 * get the element_class from the current corlib.
9951 ec = default_class_from_mono_type (enum_basetype);
9952 klass->instance_size = ec->instance_size;
9953 klass->size_inited = 1;
9955 * this is almost safe to do with enums and it's needed to be able
9956 * to create objects of the enum type (for use in SetConstant).
9958 /* FIXME: Does this mean enums can't have method overrides ? */
9959 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9961 mono_loader_unlock ();
9964 static MonoMarshalSpec*
9965 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9966 MonoReflectionMarshal *minfo)
9968 MonoMarshalSpec *res;
9970 res = image_g_new0 (image, MonoMarshalSpec, 1);
9971 res->native = minfo->type;
9973 switch (minfo->type) {
9974 case MONO_NATIVE_LPARRAY:
9975 res->data.array_data.elem_type = minfo->eltype;
9976 if (minfo->has_size) {
9977 res->data.array_data.param_num = minfo->param_num;
9978 res->data.array_data.num_elem = minfo->count;
9979 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9982 res->data.array_data.param_num = -1;
9983 res->data.array_data.num_elem = -1;
9984 res->data.array_data.elem_mult = -1;
9988 case MONO_NATIVE_BYVALTSTR:
9989 case MONO_NATIVE_BYVALARRAY:
9990 res->data.array_data.num_elem = minfo->count;
9993 case MONO_NATIVE_CUSTOM:
9994 if (minfo->marshaltyperef)
9995 res->data.custom_data.custom_name =
9996 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9998 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10007 #endif /* !DISABLE_REFLECTION_EMIT */
10009 MonoReflectionMarshal*
10010 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10011 MonoMarshalSpec *spec)
10013 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10014 MonoReflectionMarshal *minfo;
10017 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10018 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10019 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10020 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10023 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10024 minfo->type = spec->native;
10026 switch (minfo->type) {
10027 case MONO_NATIVE_LPARRAY:
10028 minfo->eltype = spec->data.array_data.elem_type;
10029 minfo->count = spec->data.array_data.num_elem;
10030 minfo->param_num = spec->data.array_data.param_num;
10033 case MONO_NATIVE_BYVALTSTR:
10034 case MONO_NATIVE_BYVALARRAY:
10035 minfo->count = spec->data.array_data.num_elem;
10038 case MONO_NATIVE_CUSTOM:
10039 if (spec->data.custom_data.custom_name) {
10040 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10042 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10044 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10046 if (spec->data.custom_data.cookie)
10047 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10057 #ifndef DISABLE_REFLECTION_EMIT
10059 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10060 ReflectionMethodBuilder *rmb,
10061 MonoMethodSignature *sig)
10065 MonoMethodWrapper *wrapperm;
10066 MonoMarshalSpec **specs;
10067 MonoReflectionMethodAux *method_aux;
10072 mono_error_init (&error);
10074 * Methods created using a MethodBuilder should have their memory allocated
10075 * inside the image mempool, while dynamic methods should have their memory
10078 dynamic = rmb->refs != NULL;
10079 image = dynamic ? NULL : klass->image;
10082 g_assert (!klass->generic_class);
10084 mono_loader_lock ();
10086 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10087 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10088 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10090 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10092 wrapperm = (MonoMethodWrapper*)m;
10094 m->dynamic = dynamic;
10096 m->flags = rmb->attrs;
10097 m->iflags = rmb->iattrs;
10098 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10100 m->signature = sig;
10101 m->sre_method = TRUE;
10102 m->skip_visibility = rmb->skip_visibility;
10103 if (rmb->table_idx)
10104 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10106 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10107 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10108 m->string_ctor = 1;
10110 m->signature->pinvoke = 1;
10111 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10112 m->signature->pinvoke = 1;
10114 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10116 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10117 g_assert (mono_error_ok (&error));
10118 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10119 g_assert (mono_error_ok (&error));
10121 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10123 if (klass->image->dynamic)
10124 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10126 mono_loader_unlock ();
10129 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10130 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10131 MonoMethodHeader *header;
10133 gint32 max_stack, i;
10134 gint32 num_locals = 0;
10135 gint32 num_clauses = 0;
10139 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10140 code_size = rmb->ilgen->code_len;
10141 max_stack = rmb->ilgen->max_stack;
10142 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10143 if (rmb->ilgen->ex_handlers)
10144 num_clauses = method_count_clauses (rmb->ilgen);
10147 code = mono_array_addr (rmb->code, guint8, 0);
10148 code_size = mono_array_length (rmb->code);
10149 /* we probably need to run a verifier on the code... */
10159 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10160 header->code_size = code_size;
10161 header->code = image_g_malloc (image, code_size);
10162 memcpy ((char*)header->code, code, code_size);
10163 header->max_stack = max_stack;
10164 header->init_locals = rmb->init_locals;
10165 header->num_locals = num_locals;
10167 for (i = 0; i < num_locals; ++i) {
10168 MonoReflectionLocalBuilder *lb =
10169 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10171 header->locals [i] = image_g_new0 (image, MonoType, 1);
10172 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10175 header->num_clauses = num_clauses;
10177 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10178 rmb->ilgen, num_clauses);
10181 wrapperm->header = header;
10184 if (rmb->generic_params) {
10185 int count = mono_array_length (rmb->generic_params);
10186 MonoGenericContainer *container = rmb->generic_container;
10188 g_assert (container);
10190 container->type_argc = count;
10191 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10192 container->owner.method = m;
10194 m->is_generic = TRUE;
10195 mono_method_set_generic_container (m, container);
10197 for (i = 0; i < count; i++) {
10198 MonoReflectionGenericParam *gp =
10199 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10200 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10201 container->type_params [i] = *param;
10205 * The method signature might have pointers to generic parameters that belong to other methods.
10206 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10207 * generic parameters.
10209 for (i = 0; i < m->signature->param_count; ++i) {
10210 MonoType *t = m->signature->params [i];
10211 if (t->type == MONO_TYPE_MVAR) {
10212 MonoGenericParam *gparam = t->data.generic_param;
10213 if (gparam->num < count) {
10214 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10215 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10221 if (klass->generic_container) {
10222 container->parent = klass->generic_container;
10223 container->context.class_inst = klass->generic_container->context.class_inst;
10225 container->context.method_inst = mono_get_shared_generic_inst (container);
10229 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10233 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10235 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10236 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10237 for (i = 0; i < rmb->nrefs; ++i)
10238 data [i + 1] = rmb->refs [i];
10243 /* Parameter info */
10246 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10247 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10248 for (i = 0; i <= m->signature->param_count; ++i) {
10249 MonoReflectionParamBuilder *pb;
10250 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10251 if ((i > 0) && (pb->attrs)) {
10252 /* Make a copy since it might point to a shared type structure */
10253 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10254 m->signature->params [i - 1]->attrs = pb->attrs;
10257 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10258 MonoDynamicImage *assembly;
10259 guint32 idx, def_type, len;
10263 if (!method_aux->param_defaults) {
10264 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10265 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10267 assembly = (MonoDynamicImage*)klass->image;
10268 idx = encode_constant (assembly, pb->def_value, &def_type);
10269 /* Copy the data from the blob since it might get realloc-ed */
10270 p = assembly->blob.data + idx;
10271 len = mono_metadata_decode_blob_size (p, &p2);
10273 method_aux->param_defaults [i] = image_g_malloc (image, len);
10274 method_aux->param_default_types [i] = def_type;
10275 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10279 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10280 g_assert (mono_error_ok (&error));
10283 if (!method_aux->param_cattr)
10284 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10285 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10291 /* Parameter marshalling */
10294 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10295 MonoReflectionParamBuilder *pb;
10296 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10297 if (pb->marshal_info) {
10299 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10300 specs [pb->position] =
10301 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10305 if (specs != NULL) {
10307 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10308 method_aux->param_marshall = specs;
10311 if (klass->image->dynamic && method_aux)
10312 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10314 mono_loader_unlock ();
10320 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10322 ReflectionMethodBuilder rmb;
10323 MonoMethodSignature *sig;
10325 mono_loader_lock ();
10326 sig = ctor_builder_to_signature (klass->image, mb);
10327 mono_loader_unlock ();
10329 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10331 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10332 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10334 /* If we are in a generic class, we might be called multiple times from inflate_method */
10335 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10336 /* ilgen is no longer needed */
10340 return mb->mhandle;
10344 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10346 ReflectionMethodBuilder rmb;
10347 MonoMethodSignature *sig;
10349 mono_loader_lock ();
10350 sig = method_builder_to_signature (klass->image, mb);
10351 mono_loader_unlock ();
10353 reflection_methodbuilder_from_method_builder (&rmb, mb);
10355 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10356 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10358 /* If we are in a generic class, we might be called multiple times from inflate_method */
10359 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10360 /* ilgen is no longer needed */
10363 return mb->mhandle;
10366 static MonoClassField*
10367 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10369 MonoClassField *field;
10373 field = g_new0 (MonoClassField, 1);
10375 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10376 g_assert (mono_error_ok (&error));
10377 if (fb->attrs || fb->modreq || fb->modopt) {
10378 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10379 field->type->attrs = fb->attrs;
10381 g_assert (klass->image->dynamic);
10382 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10383 g_free (field->type);
10384 field->type = mono_metadata_type_dup (klass->image, custom);
10387 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10389 if (fb->offset != -1)
10390 field->offset = fb->offset;
10391 field->parent = klass;
10392 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10394 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10401 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10404 MonoReflectionTypeBuilder *tb = NULL;
10405 gboolean is_dynamic = FALSE;
10406 MonoDomain *domain;
10407 MonoClass *geninst;
10409 mono_loader_lock ();
10411 domain = mono_object_domain (type);
10413 if (is_sre_type_builder (mono_object_class (type))) {
10414 tb = (MonoReflectionTypeBuilder *) type;
10417 } else if (is_sre_generic_instance (mono_object_class (type))) {
10418 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10419 MonoReflectionType *gtd = rgi->generic_type;
10421 if (is_sre_type_builder (mono_object_class (gtd))) {
10422 tb = (MonoReflectionTypeBuilder *)gtd;
10427 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10428 if (tb && tb->generic_container)
10429 mono_reflection_create_generic_class (tb);
10431 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10432 if (!klass->generic_container) {
10433 mono_loader_unlock ();
10437 if (klass->wastypebuilder) {
10438 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10443 mono_loader_unlock ();
10445 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10447 return &geninst->byval_arg;
10451 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10453 MonoGenericClass *gclass;
10454 MonoGenericInst *inst;
10456 g_assert (klass->generic_container);
10458 inst = mono_metadata_get_generic_inst (type_argc, types);
10459 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10461 return mono_generic_class_get_class (gclass);
10464 MonoReflectionMethod*
10465 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10468 MonoMethod *method, *inflated;
10469 MonoMethodInflated *imethod;
10470 MonoGenericContext tmp_context;
10471 MonoGenericInst *ginst;
10472 MonoType **type_argv;
10475 MONO_ARCH_SAVE_REGS;
10477 /*FIXME but this no longer should happen*/
10478 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10479 #ifndef DISABLE_REFLECTION_EMIT
10480 MonoReflectionMethodBuilder *mb = NULL;
10481 MonoReflectionTypeBuilder *tb;
10484 mb = (MonoReflectionMethodBuilder *) rmethod;
10485 tb = (MonoReflectionTypeBuilder *) mb->type;
10486 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10488 method = methodbuilder_to_mono_method (klass, mb);
10490 g_assert_not_reached ();
10494 method = rmethod->method;
10497 klass = method->klass;
10499 if (method->is_inflated)
10500 method = ((MonoMethodInflated *) method)->declaring;
10502 count = mono_method_signature (method)->generic_param_count;
10503 if (count != mono_array_length (types))
10506 type_argv = g_new0 (MonoType *, count);
10507 for (i = 0; i < count; i++) {
10508 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10509 type_argv [i] = mono_reflection_type_get_handle (garg);
10511 ginst = mono_metadata_get_generic_inst (count, type_argv);
10512 g_free (type_argv);
10514 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10515 tmp_context.method_inst = ginst;
10517 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10518 imethod = (MonoMethodInflated *) inflated;
10520 /*FIXME but I think this is no longer necessary*/
10521 if (method->klass->image->dynamic) {
10522 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10524 * This table maps metadata structures representing inflated methods/fields
10525 * to the reflection objects representing their generic definitions.
10527 mono_loader_lock ();
10528 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10529 mono_loader_unlock ();
10532 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10533 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10535 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10538 #ifndef DISABLE_REFLECTION_EMIT
10540 static MonoMethod *
10541 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10543 MonoMethodInflated *imethod;
10544 MonoGenericContext *context;
10548 * With generic code sharing the klass might not be inflated.
10549 * This can happen because classes inflated with their own
10550 * type arguments are "normalized" to the uninflated class.
10552 if (!klass->generic_class)
10555 context = mono_class_get_context (klass);
10557 if (klass->method.count && klass->methods) {
10558 /* Find the already created inflated method */
10559 for (i = 0; i < klass->method.count; ++i) {
10560 g_assert (klass->methods [i]->is_inflated);
10561 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10564 g_assert (i < klass->method.count);
10565 imethod = (MonoMethodInflated*)klass->methods [i];
10567 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10570 if (method->is_generic && method->klass->image->dynamic) {
10571 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10573 mono_loader_lock ();
10574 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10575 mono_loader_unlock ();
10577 return (MonoMethod *) imethod;
10580 static MonoMethod *
10581 inflate_method (MonoReflectionType *type, MonoObject *obj)
10583 MonoMethod *method;
10586 MonoClass *type_class = mono_object_class (type);
10588 if (is_sre_generic_instance (type_class)) {
10589 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10590 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10591 } else if (is_sre_type_builder (type_class)) {
10592 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10593 } else if (type->type) {
10594 gklass = mono_class_from_mono_type (type->type);
10595 gklass = mono_class_get_generic_type_definition (gklass);
10597 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10600 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10601 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10602 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10604 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10605 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10606 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10607 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10608 method = ((MonoReflectionMethod *) obj)->method;
10610 method = NULL; /* prevent compiler warning */
10611 g_error ("can't handle type %s", obj->vtable->klass->name);
10614 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10617 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10619 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10620 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10623 MonoGenericClass *gclass;
10624 MonoDynamicGenericClass *dgclass;
10625 MonoClass *klass, *gklass;
10629 MONO_ARCH_SAVE_REGS;
10631 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10632 klass = mono_class_from_mono_type (gtype);
10633 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10634 gclass = gtype->data.generic_class;
10636 if (!gclass->is_dynamic)
10639 dgclass = (MonoDynamicGenericClass *) gclass;
10641 if (dgclass->initialized)
10644 gklass = gclass->container_class;
10645 mono_class_init (gklass);
10647 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10649 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10650 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10651 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10653 for (i = 0; i < dgclass->count_fields; i++) {
10654 MonoObject *obj = mono_array_get (fields, gpointer, i);
10655 MonoClassField *field, *inflated_field = NULL;
10657 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10658 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10659 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10660 field = ((MonoReflectionField *) obj)->field;
10662 field = NULL; /* prevent compiler warning */
10663 g_assert_not_reached ();
10666 dgclass->fields [i] = *field;
10667 dgclass->fields [i].parent = klass;
10668 dgclass->fields [i].type = mono_class_inflate_generic_type (
10669 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10670 dgclass->field_generic_types [i] = field->type;
10671 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10672 dgclass->field_objects [i] = obj;
10674 if (inflated_field) {
10675 g_free (inflated_field);
10677 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10681 dgclass->initialized = TRUE;
10685 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10687 MonoDynamicGenericClass *dgclass;
10690 g_assert (gclass->is_dynamic);
10692 dgclass = (MonoDynamicGenericClass *)gclass;
10694 for (i = 0; i < dgclass->count_fields; ++i) {
10695 MonoClassField *field = dgclass->fields + i;
10696 mono_metadata_free_type (field->type);
10697 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10702 fix_partial_generic_class (MonoClass *klass)
10704 MonoClass *gklass = klass->generic_class->container_class;
10705 MonoDynamicGenericClass *dgclass;
10708 if (klass->wastypebuilder)
10711 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10712 if (klass->parent != gklass->parent) {
10714 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10715 if (mono_error_ok (&error)) {
10716 MonoClass *parent = mono_class_from_mono_type (parent_type);
10717 mono_metadata_free_type (parent_type);
10718 if (parent != klass->parent) {
10719 /*fool mono_class_setup_parent*/
10720 klass->supertypes = NULL;
10721 mono_class_setup_parent (klass, parent);
10724 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10725 mono_error_cleanup (&error);
10726 if (gklass->wastypebuilder)
10727 klass->wastypebuilder = TRUE;
10732 if (!dgclass->initialized)
10735 if (klass->method.count != gklass->method.count) {
10736 klass->method.count = gklass->method.count;
10737 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10739 for (i = 0; i < klass->method.count; i++) {
10740 klass->methods [i] = mono_class_inflate_generic_method_full (
10741 gklass->methods [i], klass, mono_class_get_context (klass));
10745 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10746 klass->interface_count = gklass->interface_count;
10747 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10748 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10750 for (i = 0; i < gklass->interface_count; ++i) {
10751 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10752 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10753 mono_metadata_free_type (iface_type);
10755 ensure_runtime_vtable (klass->interfaces [i]);
10757 klass->interfaces_inited = 1;
10760 if (klass->field.count != gklass->field.count) {
10761 klass->field.count = gklass->field.count;
10762 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10764 for (i = 0; i < klass->field.count; i++) {
10765 klass->fields [i] = gklass->fields [i];
10766 klass->fields [i].parent = klass;
10767 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10771 /*We can only finish with this klass once it's parent has as well*/
10772 if (gklass->wastypebuilder)
10773 klass->wastypebuilder = TRUE;
10778 ensure_generic_class_runtime_vtable (MonoClass *klass)
10780 MonoClass *gklass = klass->generic_class->container_class;
10782 ensure_runtime_vtable (gklass);
10784 fix_partial_generic_class (klass);
10788 ensure_runtime_vtable (MonoClass *klass)
10790 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10793 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10796 ensure_runtime_vtable (klass->parent);
10799 num = tb->ctors? mono_array_length (tb->ctors): 0;
10800 num += tb->num_methods;
10801 klass->method.count = num;
10802 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10803 num = tb->ctors? mono_array_length (tb->ctors): 0;
10804 for (i = 0; i < num; ++i)
10805 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10806 num = tb->num_methods;
10808 for (i = 0; i < num; ++i)
10809 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10811 if (tb->interfaces) {
10812 klass->interface_count = mono_array_length (tb->interfaces);
10813 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10814 for (i = 0; i < klass->interface_count; ++i) {
10815 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10816 klass->interfaces [i] = mono_class_from_mono_type (iface);
10817 ensure_runtime_vtable (klass->interfaces [i]);
10819 klass->interfaces_inited = 1;
10821 } else if (klass->generic_class){
10822 ensure_generic_class_runtime_vtable (klass);
10825 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10827 for (i = 0; i < klass->method.count; ++i) {
10828 MonoMethod *im = klass->methods [i];
10829 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10830 im->slot = slot_num++;
10833 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10834 mono_class_setup_interface_offsets (klass);
10835 mono_class_setup_interface_id (klass);
10839 * The generic vtable is needed even if image->run is not set since some
10840 * runtime code like ves_icall_Type_GetMethodsByName depends on
10841 * method->slot being defined.
10845 * tb->methods could not be freed since it is used for determining
10846 * overrides during dynamic vtable construction.
10851 mono_reflection_method_get_handle (MonoObject *method)
10853 MonoClass *class = mono_object_class (method);
10854 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10855 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10856 return sr_method->method;
10858 if (is_sre_method_builder (class)) {
10859 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10860 return mb->mhandle;
10862 if (is_sre_method_on_tb_inst (class)) {
10863 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10864 MonoMethod *result;
10865 /*FIXME move this to a proper method and unify with resolve_object*/
10866 if (m->method_args) {
10867 result = mono_reflection_method_on_tb_inst_get_handle (m);
10869 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10870 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10871 MonoMethod *mono_method;
10873 if (is_sre_method_builder (mono_object_class (m->mb)))
10874 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10875 else if (is_sr_mono_method (mono_object_class (m->mb)))
10876 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10878 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)));
10880 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10885 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10890 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10892 MonoReflectionTypeBuilder *tb;
10894 MonoReflectionMethod *m;
10897 *num_overrides = 0;
10899 g_assert (klass->image->dynamic);
10901 if (!mono_class_get_ref_info (klass))
10904 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10906 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10910 for (i = 0; i < tb->num_methods; ++i) {
10911 MonoReflectionMethodBuilder *mb =
10912 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10913 if (mb->override_methods)
10914 onum += mono_array_length (mb->override_methods);
10919 *overrides = g_new0 (MonoMethod*, onum * 2);
10922 for (i = 0; i < tb->num_methods; ++i) {
10923 MonoReflectionMethodBuilder *mb =
10924 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10925 if (mb->override_methods) {
10926 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10927 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10929 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10930 (*overrides) [onum * 2 + 1] = mb->mhandle;
10932 g_assert (mb->mhandle);
10940 *num_overrides = onum;
10944 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10946 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10947 MonoReflectionFieldBuilder *fb;
10948 MonoClassField *field;
10949 MonoImage *image = klass->image;
10950 const char *p, *p2;
10952 guint32 len, idx, real_size = 0;
10954 klass->field.count = tb->num_fields;
10955 klass->field.first = 0;
10957 mono_error_init (error);
10959 if (tb->class_size) {
10960 if ((tb->packing_size & 0xfffffff0) != 0) {
10961 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10962 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10965 klass->packing_size = tb->packing_size;
10966 real_size = klass->instance_size + tb->class_size;
10969 if (!klass->field.count) {
10970 klass->instance_size = MAX (klass->instance_size, real_size);
10974 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10975 mono_class_alloc_ext (klass);
10976 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10978 This is, guess what, a hack.
10979 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10980 On the static path no field class is resolved, only types are built. This is the right thing to do
10982 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10984 klass->size_inited = 1;
10986 for (i = 0; i < klass->field.count; ++i) {
10987 MonoArray *rva_data;
10988 fb = mono_array_get (tb->fields, gpointer, i);
10989 field = &klass->fields [i];
10990 field->name = mono_string_to_utf8_image (image, fb->name, error);
10991 if (!mono_error_ok (error))
10994 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10995 field->type->attrs = fb->attrs;
10997 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11000 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11001 char *base = mono_array_addr (rva_data, char, 0);
11002 size_t size = mono_array_length (rva_data);
11003 char *data = mono_image_alloc (klass->image, size);
11004 memcpy (data, base, size);
11005 klass->ext->field_def_values [i].data = data;
11007 if (fb->offset != -1)
11008 field->offset = fb->offset;
11009 field->parent = klass;
11010 fb->handle = field;
11011 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11013 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11014 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11016 if (fb->def_value) {
11017 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11018 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11019 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11020 /* Copy the data from the blob since it might get realloc-ed */
11021 p = assembly->blob.data + idx;
11022 len = mono_metadata_decode_blob_size (p, &p2);
11024 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11025 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11029 klass->instance_size = MAX (klass->instance_size, real_size);
11030 mono_class_layout_fields (klass);
11034 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11036 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11037 MonoReflectionPropertyBuilder *pb;
11038 MonoImage *image = klass->image;
11039 MonoProperty *properties;
11042 mono_error_init (error);
11045 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11047 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11048 klass->ext->property.first = 0;
11050 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11051 klass->ext->properties = properties;
11052 for (i = 0; i < klass->ext->property.count; ++i) {
11053 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11054 properties [i].parent = klass;
11055 properties [i].attrs = pb->attrs;
11056 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11057 if (!mono_error_ok (error))
11059 if (pb->get_method)
11060 properties [i].get = pb->get_method->mhandle;
11061 if (pb->set_method)
11062 properties [i].set = pb->set_method->mhandle;
11064 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11065 if (pb->def_value) {
11067 const char *p, *p2;
11068 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11069 if (!klass->ext->prop_def_values)
11070 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11071 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11072 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11073 /* Copy the data from the blob since it might get realloc-ed */
11074 p = assembly->blob.data + idx;
11075 len = mono_metadata_decode_blob_size (p, &p2);
11077 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11078 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11083 MonoReflectionEvent *
11084 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11086 MonoEvent *event = g_new0 (MonoEvent, 1);
11089 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11091 event->parent = klass;
11092 event->attrs = eb->attrs;
11093 event->name = mono_string_to_utf8 (eb->name);
11094 if (eb->add_method)
11095 event->add = eb->add_method->mhandle;
11096 if (eb->remove_method)
11097 event->remove = eb->remove_method->mhandle;
11098 if (eb->raise_method)
11099 event->raise = eb->raise_method->mhandle;
11101 #ifndef MONO_SMALL_CONFIG
11102 if (eb->other_methods) {
11104 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11105 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11106 MonoReflectionMethodBuilder *mb =
11107 mono_array_get (eb->other_methods,
11108 MonoReflectionMethodBuilder*, j);
11109 event->other [j] = mb->mhandle;
11114 return mono_event_get_object (mono_object_domain (tb), klass, event);
11118 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11120 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11121 MonoReflectionEventBuilder *eb;
11122 MonoImage *image = klass->image;
11126 mono_error_init (error);
11129 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11131 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11132 klass->ext->event.first = 0;
11134 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11135 klass->ext->events = events;
11136 for (i = 0; i < klass->ext->event.count; ++i) {
11137 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11138 events [i].parent = klass;
11139 events [i].attrs = eb->attrs;
11140 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11141 if (!mono_error_ok (error))
11143 if (eb->add_method)
11144 events [i].add = eb->add_method->mhandle;
11145 if (eb->remove_method)
11146 events [i].remove = eb->remove_method->mhandle;
11147 if (eb->raise_method)
11148 events [i].raise = eb->raise_method->mhandle;
11150 #ifndef MONO_SMALL_CONFIG
11151 if (eb->other_methods) {
11153 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11154 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11155 MonoReflectionMethodBuilder *mb =
11156 mono_array_get (eb->other_methods,
11157 MonoReflectionMethodBuilder*, j);
11158 events [i].other [j] = mb->mhandle;
11162 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11167 remove_instantiations_of_and_ensure_contents (gpointer key,
11169 gpointer user_data)
11171 MonoType *type = (MonoType*)key;
11172 MonoClass *klass = (MonoClass*)user_data;
11174 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11175 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11182 check_array_for_usertypes (MonoArray *arr)
11189 for (i = 0; i < mono_array_length (arr); ++i)
11190 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11193 MonoReflectionType*
11194 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11198 MonoDomain* domain;
11199 MonoReflectionType* res;
11202 MONO_ARCH_SAVE_REGS;
11204 domain = mono_object_domain (tb);
11205 klass = mono_class_from_mono_type (tb->type.type);
11208 * Check for user defined Type subclasses.
11210 RESOLVE_TYPE (tb->parent);
11211 check_array_for_usertypes (tb->interfaces);
11213 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11214 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11216 RESOLVE_TYPE (fb->type);
11217 check_array_for_usertypes (fb->modreq);
11218 check_array_for_usertypes (fb->modopt);
11219 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11220 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11225 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11226 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11228 RESOLVE_TYPE (mb->rtype);
11229 check_array_for_usertypes (mb->return_modreq);
11230 check_array_for_usertypes (mb->return_modopt);
11231 check_array_for_usertypes (mb->parameters);
11232 if (mb->param_modreq)
11233 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11234 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11235 if (mb->param_modopt)
11236 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11237 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11242 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11243 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11245 check_array_for_usertypes (mb->parameters);
11246 if (mb->param_modreq)
11247 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11248 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11249 if (mb->param_modopt)
11250 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11251 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11256 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11259 * we need to lock the domain because the lock will be taken inside
11260 * So, we need to keep the locking order correct.
11262 mono_loader_lock ();
11263 mono_domain_lock (domain);
11264 if (klass->wastypebuilder) {
11265 mono_domain_unlock (domain);
11266 mono_loader_unlock ();
11267 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11270 * Fields to set in klass:
11271 * the various flags: delegate/unicode/contextbound etc.
11273 klass->flags = tb->attrs;
11274 klass->has_cctor = 1;
11275 klass->has_finalize = 1;
11276 klass->has_finalize_inited = 1;
11278 /* fool mono_class_setup_parent */
11279 klass->supertypes = NULL;
11280 mono_class_setup_parent (klass, klass->parent);
11281 mono_class_setup_mono_type (klass);
11284 if (!((MonoDynamicImage*)klass->image)->run) {
11285 if (klass->generic_container) {
11286 /* FIXME: The code below can't handle generic classes */
11287 klass->wastypebuilder = TRUE;
11288 mono_loader_unlock ();
11289 mono_domain_unlock (domain);
11290 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11295 /* enums are done right away */
11296 if (!klass->enumtype)
11297 ensure_runtime_vtable (klass);
11299 if (tb->subtypes) {
11300 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11301 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11302 mono_class_alloc_ext (klass);
11303 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)));
11307 klass->nested_classes_inited = TRUE;
11309 /* fields and object layout */
11310 if (klass->parent) {
11311 if (!klass->parent->size_inited)
11312 mono_class_init (klass->parent);
11313 klass->instance_size = klass->parent->instance_size;
11314 klass->sizes.class_size = 0;
11315 klass->min_align = klass->parent->min_align;
11316 /* if the type has no fields we won't call the field_setup
11317 * routine which sets up klass->has_references.
11319 klass->has_references |= klass->parent->has_references;
11321 klass->instance_size = sizeof (MonoObject);
11322 klass->min_align = 1;
11325 /* FIXME: handle packing_size and instance_size */
11326 typebuilder_setup_fields (klass, &error);
11327 if (!mono_error_ok (&error))
11329 typebuilder_setup_properties (klass, &error);
11330 if (!mono_error_ok (&error))
11333 typebuilder_setup_events (klass, &error);
11334 if (!mono_error_ok (&error))
11337 klass->wastypebuilder = TRUE;
11340 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11341 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11342 * we want to return normal System.MonoType objects, so clear these out from the cache.
11344 * Together with this we must ensure the contents of all instances to match the created type.
11346 if (domain->type_hash && klass->generic_container)
11347 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11349 mono_domain_unlock (domain);
11350 mono_loader_unlock ();
11352 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11353 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11354 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11357 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11358 g_assert (res != (MonoReflectionType*)tb);
11363 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11364 klass->wastypebuilder = TRUE;
11365 mono_domain_unlock (domain);
11366 mono_loader_unlock ();
11367 mono_error_raise_exception (&error);
11372 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11374 MonoGenericParamFull *param;
11379 MONO_ARCH_SAVE_REGS;
11381 image = &gparam->tbuilder->module->dynamic_image->image;
11383 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11385 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11386 g_assert (mono_error_ok (&error));
11387 param->param.num = gparam->index;
11389 if (gparam->mbuilder) {
11390 if (!gparam->mbuilder->generic_container) {
11391 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11392 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11393 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11394 gparam->mbuilder->generic_container->is_method = TRUE;
11396 * Cannot set owner.method, since the MonoMethod is not created yet.
11397 * Set the image field instead, so type_in_image () works.
11399 gparam->mbuilder->generic_container->image = klass->image;
11401 param->param.owner = gparam->mbuilder->generic_container;
11402 } else if (gparam->tbuilder) {
11403 if (!gparam->tbuilder->generic_container) {
11404 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11405 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11406 gparam->tbuilder->generic_container->owner.klass = klass;
11408 param->param.owner = gparam->tbuilder->generic_container;
11411 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11413 gparam->type.type = &pklass->byval_arg;
11415 mono_class_set_ref_info (pklass, gparam);
11416 mono_image_lock (image);
11417 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11418 mono_image_unlock (image);
11422 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11424 MonoReflectionModuleBuilder *module = sig->module;
11425 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11426 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11431 check_array_for_usertypes (sig->arguments);
11433 sigbuffer_init (&buf, 32);
11435 sigbuffer_add_value (&buf, 0x07);
11436 sigbuffer_add_value (&buf, na);
11437 if (assembly != NULL){
11438 for (i = 0; i < na; ++i) {
11439 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11440 encode_reflection_type (assembly, type, &buf);
11444 buflen = buf.p - buf.buf;
11445 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11446 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11447 sigbuffer_free (&buf);
11453 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11455 MonoDynamicImage *assembly = sig->module->dynamic_image;
11456 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11461 check_array_for_usertypes (sig->arguments);
11463 sigbuffer_init (&buf, 32);
11465 sigbuffer_add_value (&buf, 0x06);
11466 for (i = 0; i < na; ++i) {
11467 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11468 encode_reflection_type (assembly, type, &buf);
11471 buflen = buf.p - buf.buf;
11472 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11473 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11474 sigbuffer_free (&buf);
11480 MonoMethod *handle;
11481 MonoDomain *domain;
11482 } DynamicMethodReleaseData;
11485 * The runtime automatically clean up those after finalization.
11487 static MonoReferenceQueue *dynamic_method_queue;
11490 free_dynamic_method (void *dynamic_method)
11492 DynamicMethodReleaseData *data = dynamic_method;
11494 mono_runtime_free_method (data->domain, data->handle);
11499 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11501 MonoReferenceQueue *queue;
11502 MonoMethod *handle;
11503 DynamicMethodReleaseData *release_data;
11504 ReflectionMethodBuilder rmb;
11505 MonoMethodSignature *sig;
11510 if (mono_runtime_is_shutting_down ())
11511 mono_raise_exception (mono_get_exception_invalid_operation (""));
11513 if (!(queue = dynamic_method_queue)) {
11514 mono_loader_lock ();
11515 if (!(queue = dynamic_method_queue))
11516 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11517 mono_loader_unlock ();
11520 sig = dynamic_method_to_signature (mb);
11522 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11525 * Resolve references.
11528 * Every second entry in the refs array is reserved for storing handle_class,
11529 * which is needed by the ldtoken implementation in the JIT.
11531 rmb.nrefs = mb->nrefs;
11532 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11533 for (i = 0; i < mb->nrefs; i += 2) {
11534 MonoClass *handle_class;
11536 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11538 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11539 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11541 * The referenced DynamicMethod should already be created by the managed
11542 * code, except in the case of circular references. In that case, we store
11543 * method in the refs array, and fix it up later when the referenced
11544 * DynamicMethod is created.
11546 if (method->mhandle) {
11547 ref = method->mhandle;
11549 /* FIXME: GC object stored in unmanaged memory */
11552 /* FIXME: GC object stored in unmanaged memory */
11553 method->referenced_by = g_slist_append (method->referenced_by, mb);
11555 handle_class = mono_defaults.methodhandle_class;
11557 MonoException *ex = NULL;
11558 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11560 ex = mono_get_exception_type_load (NULL, NULL);
11561 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11562 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11566 mono_raise_exception (ex);
11571 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11572 rmb.refs [i + 1] = handle_class;
11575 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11577 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11578 release_data = g_new (DynamicMethodReleaseData, 1);
11579 release_data->handle = handle;
11580 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11581 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11582 g_free (release_data);
11584 /* Fix up refs entries pointing at us */
11585 for (l = mb->referenced_by; l; l = l->next) {
11586 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11587 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11590 g_assert (method->mhandle);
11592 data = (gpointer*)wrapper->method_data;
11593 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11594 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11595 data [i + 1] = mb->mhandle;
11598 g_slist_free (mb->referenced_by);
11602 /* ilgen is no longer needed */
11606 #endif /* DISABLE_REFLECTION_EMIT */
11610 * mono_reflection_is_valid_dynamic_token:
11612 * Returns TRUE if token is valid.
11616 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11618 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11621 MonoMethodSignature *
11622 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11624 MonoMethodSignature *sig;
11625 g_assert (image->dynamic);
11627 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11631 return mono_method_signature (method);
11634 #ifndef DISABLE_REFLECTION_EMIT
11637 * mono_reflection_lookup_dynamic_token:
11639 * Finish the Builder object pointed to by TOKEN and return the corresponding
11640 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11641 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11644 * LOCKING: Take the loader lock
11647 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11649 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11653 mono_loader_lock ();
11654 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11655 mono_loader_unlock ();
11658 g_error ("Could not find required dynamic token 0x%08x", token);
11664 handle_class = &klass;
11665 return resolve_object (image, obj, handle_class, context);
11669 * ensure_complete_type:
11671 * Ensure that KLASS is completed if it is a dynamic type, or references
11675 ensure_complete_type (MonoClass *klass)
11677 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11678 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11680 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11682 // Asserting here could break a lot of code
11683 //g_assert (klass->wastypebuilder);
11686 if (klass->generic_class) {
11687 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11690 for (i = 0; i < inst->type_argc; ++i) {
11691 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11697 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11699 gpointer result = NULL;
11701 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11702 result = mono_string_intern ((MonoString*)obj);
11703 *handle_class = mono_defaults.string_class;
11705 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11706 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11707 MonoClass *mc = mono_class_from_mono_type (type);
11708 if (!mono_class_init (mc))
11709 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11712 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11713 result = mono_class_from_mono_type (inflated);
11714 mono_metadata_free_type (inflated);
11716 result = mono_class_from_mono_type (type);
11718 *handle_class = mono_defaults.typehandle_class;
11720 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11721 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11722 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11723 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11724 result = ((MonoReflectionMethod*)obj)->method;
11726 result = mono_class_inflate_generic_method (result, context);
11727 *handle_class = mono_defaults.methodhandle_class;
11729 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11730 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11731 result = mb->mhandle;
11733 /* Type is not yet created */
11734 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11736 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11739 * Hopefully this has been filled in by calling CreateType() on the
11743 * TODO: This won't work if the application finishes another
11744 * TypeBuilder instance instead of this one.
11746 result = mb->mhandle;
11749 result = mono_class_inflate_generic_method (result, context);
11750 *handle_class = mono_defaults.methodhandle_class;
11751 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11752 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11754 result = cb->mhandle;
11756 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11758 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11759 result = cb->mhandle;
11762 result = mono_class_inflate_generic_method (result, context);
11763 *handle_class = mono_defaults.methodhandle_class;
11764 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11765 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11767 ensure_complete_type (field->parent);
11769 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11770 MonoClass *class = mono_class_from_mono_type (inflated);
11771 MonoClassField *inflated_field;
11772 gpointer iter = NULL;
11773 mono_metadata_free_type (inflated);
11774 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11775 if (!strcmp (field->name, inflated_field->name))
11778 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11779 result = inflated_field;
11783 *handle_class = mono_defaults.fieldhandle_class;
11785 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11786 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11787 result = fb->handle;
11790 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11792 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11793 result = fb->handle;
11796 if (fb->handle && fb->handle->parent->generic_container) {
11797 MonoClass *klass = fb->handle->parent;
11798 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11799 MonoClass *inflated = mono_class_from_mono_type (type);
11801 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11803 mono_metadata_free_type (type);
11805 *handle_class = mono_defaults.fieldhandle_class;
11806 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11807 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11808 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11811 klass = type->data.klass;
11812 if (klass->wastypebuilder) {
11813 /* Already created */
11817 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11818 result = type->data.klass;
11821 *handle_class = mono_defaults.typehandle_class;
11822 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11823 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11824 MonoMethodSignature *sig;
11827 if (helper->arguments)
11828 nargs = mono_array_length (helper->arguments);
11832 sig = mono_metadata_signature_alloc (image, nargs);
11833 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11834 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11836 if (helper->unmanaged_call_conv) { /* unmanaged */
11837 sig->call_convention = helper->unmanaged_call_conv - 1;
11838 sig->pinvoke = TRUE;
11839 } else if (helper->call_conv & 0x02) {
11840 sig->call_convention = MONO_CALL_VARARG;
11842 sig->call_convention = MONO_CALL_DEFAULT;
11845 sig->param_count = nargs;
11846 /* TODO: Copy type ? */
11847 sig->ret = helper->return_type->type;
11848 for (i = 0; i < nargs; ++i)
11849 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11852 *handle_class = NULL;
11853 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11854 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11855 /* Already created by the managed code */
11856 g_assert (method->mhandle);
11857 result = method->mhandle;
11858 *handle_class = mono_defaults.methodhandle_class;
11859 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11860 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11861 type = mono_class_inflate_generic_type (type, context);
11862 result = mono_class_from_mono_type (type);
11863 *handle_class = mono_defaults.typehandle_class;
11865 mono_metadata_free_type (type);
11866 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11867 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11868 type = mono_class_inflate_generic_type (type, context);
11869 result = mono_class_from_mono_type (type);
11870 *handle_class = mono_defaults.typehandle_class;
11872 mono_metadata_free_type (type);
11873 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11874 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11875 MonoClass *inflated;
11877 MonoClassField *field;
11879 if (is_sre_field_builder (mono_object_class (f->fb)))
11880 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11881 else if (is_sr_mono_field (mono_object_class (f->fb)))
11882 field = ((MonoReflectionField*)f->fb)->field;
11884 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)));
11886 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11887 inflated = mono_class_from_mono_type (type);
11889 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11890 ensure_complete_type (field->parent);
11892 mono_metadata_free_type (type);
11893 *handle_class = mono_defaults.fieldhandle_class;
11894 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11895 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11896 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11897 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11898 MonoMethod *method;
11900 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11901 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11902 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11903 method = ((MonoReflectionMethod *)c->cb)->method;
11905 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)));
11907 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11908 *handle_class = mono_defaults.methodhandle_class;
11909 mono_metadata_free_type (type);
11910 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11911 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11912 if (m->method_args) {
11913 result = mono_reflection_method_on_tb_inst_get_handle (m);
11915 result = mono_class_inflate_generic_method (result, context);
11917 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11918 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11919 MonoMethod *method;
11921 if (is_sre_method_builder (mono_object_class (m->mb)))
11922 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11923 else if (is_sr_mono_method (mono_object_class (m->mb)))
11924 method = ((MonoReflectionMethod *)m->mb)->method;
11926 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)));
11928 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11929 mono_metadata_free_type (type);
11931 *handle_class = mono_defaults.methodhandle_class;
11932 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11933 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11936 MonoMethod *method;
11940 mtype = mono_reflection_type_get_handle (m->parent);
11941 klass = mono_class_from_mono_type (mtype);
11943 /* Find the method */
11945 name = mono_string_to_utf8 (m->name);
11947 while ((method = mono_class_get_methods (klass, &iter))) {
11948 if (!strcmp (method->name, name))
11955 // FIXME: Check parameters/return value etc. match
11958 *handle_class = mono_defaults.methodhandle_class;
11959 } else if (is_sre_array (mono_object_get_class(obj)) ||
11960 is_sre_byref (mono_object_get_class(obj)) ||
11961 is_sre_pointer (mono_object_get_class(obj))) {
11962 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11963 MonoType *type = mono_reflection_type_get_handle (ref_type);
11964 result = mono_class_from_mono_type (type);
11965 *handle_class = mono_defaults.typehandle_class;
11967 g_print ("%s\n", obj->vtable->klass->name);
11968 g_assert_not_reached ();
11973 #else /* DISABLE_REFLECTION_EMIT */
11976 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11978 g_assert_not_reached ();
11983 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11985 g_assert_not_reached ();
11989 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11991 g_assert_not_reached ();
11995 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11997 g_assert_not_reached ();
12001 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12003 g_assert_not_reached ();
12007 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12009 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12013 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12015 g_assert_not_reached ();
12019 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12021 g_assert_not_reached ();
12024 MonoReflectionModule *
12025 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12027 g_assert_not_reached ();
12032 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12034 g_assert_not_reached ();
12039 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12041 g_assert_not_reached ();
12046 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12047 gboolean create_open_instance, gboolean register_token)
12049 g_assert_not_reached ();
12054 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12059 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12060 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12063 g_assert_not_reached ();
12067 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12070 *num_overrides = 0;
12073 MonoReflectionEvent *
12074 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12076 g_assert_not_reached ();
12080 MonoReflectionType*
12081 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12083 g_assert_not_reached ();
12088 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12090 g_assert_not_reached ();
12094 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12096 g_assert_not_reached ();
12101 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12103 g_assert_not_reached ();
12108 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12113 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12119 mono_reflection_type_get_handle (MonoReflectionType* ref)
12127 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12129 g_assert_not_reached ();
12132 #endif /* DISABLE_REFLECTION_EMIT */
12134 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12135 const static guint32 declsec_flags_map[] = {
12136 0x00000000, /* empty */
12137 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12138 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12139 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12140 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12141 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12142 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12143 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12144 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12145 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12146 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12147 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12148 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12149 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12150 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12151 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12152 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12153 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12154 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12158 * Returns flags that includes all available security action associated to the handle.
12159 * @token: metadata token (either for a class or a method)
12160 * @image: image where resides the metadata.
12163 mono_declsec_get_flags (MonoImage *image, guint32 token)
12165 int index = mono_metadata_declsec_from_index (image, token);
12166 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12167 guint32 result = 0;
12171 /* HasSecurity can be present for other, not specially encoded, attributes,
12172 e.g. SuppressUnmanagedCodeSecurityAttribute */
12176 for (i = index; i < t->rows; i++) {
12177 guint32 cols [MONO_DECL_SECURITY_SIZE];
12179 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12180 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12183 action = cols [MONO_DECL_SECURITY_ACTION];
12184 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12185 result |= declsec_flags_map [action];
12187 g_assert_not_reached ();
12194 * Get the security actions (in the form of flags) associated with the specified method.
12196 * @method: The method for which we want the declarative security flags.
12197 * Return the declarative security flags for the method (only).
12199 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12200 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12203 mono_declsec_flags_from_method (MonoMethod *method)
12205 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12206 /* FIXME: No cache (for the moment) */
12207 guint32 idx = mono_method_get_index (method);
12208 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12209 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12210 return mono_declsec_get_flags (method->klass->image, idx);
12216 * Get the security actions (in the form of flags) associated with the specified class.
12218 * @klass: The class for which we want the declarative security flags.
12219 * Return the declarative security flags for the class.
12221 * Note: We cache the flags inside the MonoClass structure as this will get
12222 * called very often (at least for each method).
12225 mono_declsec_flags_from_class (MonoClass *klass)
12227 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12228 if (!klass->ext || !klass->ext->declsec_flags) {
12231 idx = mono_metadata_token_index (klass->type_token);
12232 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12233 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12234 mono_loader_lock ();
12235 mono_class_alloc_ext (klass);
12236 mono_loader_unlock ();
12237 /* we cache the flags on classes */
12238 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12240 return klass->ext->declsec_flags;
12246 * Get the security actions (in the form of flags) associated with the specified assembly.
12248 * @assembly: The assembly for which we want the declarative security flags.
12249 * Return the declarative security flags for the assembly.
12252 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12254 guint32 idx = 1; /* there is only one assembly */
12255 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12256 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12257 return mono_declsec_get_flags (assembly->image, idx);
12262 * Fill actions for the specific index (which may either be an encoded class token or
12263 * an encoded method token) from the metadata image.
12264 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12267 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12268 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12270 MonoBoolean result = FALSE;
12272 guint32 cols [MONO_DECL_SECURITY_SIZE];
12273 int index = mono_metadata_declsec_from_index (image, token);
12276 t = &image->tables [MONO_TABLE_DECLSECURITY];
12277 for (i = index; i < t->rows; i++) {
12278 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12280 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12283 /* if present only replace (class) permissions with method permissions */
12284 /* if empty accept either class or method permissions */
12285 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12286 if (!actions->demand.blob) {
12287 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12288 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12289 actions->demand.blob = (char*) (blob + 2);
12290 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12293 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12294 if (!actions->noncasdemand.blob) {
12295 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12296 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12297 actions->noncasdemand.blob = (char*) (blob + 2);
12298 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12301 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12302 if (!actions->demandchoice.blob) {
12303 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12304 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12305 actions->demandchoice.blob = (char*) (blob + 2);
12306 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12316 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12317 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12319 guint32 idx = mono_metadata_token_index (klass->type_token);
12320 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12321 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12322 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12326 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12327 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12329 guint32 idx = mono_method_get_index (method);
12330 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12331 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12332 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12336 * Collect all actions (that requires to generate code in mini) assigned for
12337 * the specified method.
12338 * Note: Don't use the content of actions if the function return FALSE.
12341 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12343 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12344 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12345 MonoBoolean result = FALSE;
12348 /* quick exit if no declarative security is present in the metadata */
12349 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12352 /* we want the original as the wrapper is "free" of the security informations */
12353 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12354 method = mono_marshal_method_from_wrapper (method);
12359 /* First we look for method-level attributes */
12360 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12361 mono_class_init (method->klass);
12362 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12364 result = mono_declsec_get_method_demands_params (method, demands,
12365 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12368 /* Here we use (or create) the class declarative cache to look for demands */
12369 flags = mono_declsec_flags_from_class (method->klass);
12370 if (flags & mask) {
12372 mono_class_init (method->klass);
12373 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12375 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12376 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12379 /* The boolean return value is used as a shortcut in case nothing needs to
12380 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12386 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12388 * Note: Don't use the content of actions if the function return FALSE.
12391 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12393 MonoBoolean result = FALSE;
12396 /* quick exit if no declarative security is present in the metadata */
12397 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12400 /* we want the original as the wrapper is "free" of the security informations */
12401 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12402 method = mono_marshal_method_from_wrapper (method);
12407 /* results are independant - zeroize both */
12408 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12409 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12411 /* First we look for method-level attributes */
12412 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12413 mono_class_init (method->klass);
12415 result = mono_declsec_get_method_demands_params (method, cmethod,
12416 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12419 /* Here we use (or create) the class declarative cache to look for demands */
12420 flags = mono_declsec_flags_from_class (method->klass);
12421 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12422 mono_class_init (method->klass);
12424 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12425 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12432 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12434 * @klass The inherited class - this is the class that provides the security check (attributes)
12436 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12438 * Note: Don't use the content of actions if the function return FALSE.
12441 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12443 MonoBoolean result = FALSE;
12446 /* quick exit if no declarative security is present in the metadata */
12447 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12450 /* Here we use (or create) the class declarative cache to look for demands */
12451 flags = mono_declsec_flags_from_class (klass);
12452 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12453 mono_class_init (klass);
12454 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12456 result |= mono_declsec_get_class_demands_params (klass, demands,
12457 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12464 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12466 * Note: Don't use the content of actions if the function return FALSE.
12469 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12471 /* quick exit if no declarative security is present in the metadata */
12472 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12475 /* we want the original as the wrapper is "free" of the security informations */
12476 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12477 method = mono_marshal_method_from_wrapper (method);
12482 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12483 mono_class_init (method->klass);
12484 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12486 return mono_declsec_get_method_demands_params (method, demands,
12487 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12494 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12496 guint32 cols [MONO_DECL_SECURITY_SIZE];
12500 int index = mono_metadata_declsec_from_index (image, token);
12504 t = &image->tables [MONO_TABLE_DECLSECURITY];
12505 for (i = index; i < t->rows; i++) {
12506 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12508 /* shortcut - index are ordered */
12509 if (token != cols [MONO_DECL_SECURITY_PARENT])
12512 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12513 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12514 entry->blob = (char*) (metadata + 2);
12515 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12524 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12526 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12527 guint32 idx = mono_method_get_index (method);
12528 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12529 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12530 return get_declsec_action (method->klass->image, idx, action, entry);
12536 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12539 guint32 flags = mono_declsec_flags_from_class (klass);
12540 if (declsec_flags_map [action] & flags) {
12541 guint32 idx = mono_metadata_token_index (klass->type_token);
12542 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12543 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12544 return get_declsec_action (klass->image, idx, action, entry);
12550 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12552 guint32 idx = 1; /* there is only one assembly */
12553 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12554 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12556 return get_declsec_action (assembly->image, idx, action, entry);
12560 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12562 MonoObject *res, *exc;
12564 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12565 static MonoMethod *method = NULL;
12567 if (!System_Reflection_Emit_TypeBuilder) {
12568 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12569 g_assert (System_Reflection_Emit_TypeBuilder);
12571 if (method == NULL) {
12572 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12577 * The result of mono_type_get_object () might be a System.MonoType but we
12578 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12580 g_assert (mono_class_get_ref_info (klass));
12581 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12583 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12585 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12589 return *(MonoBoolean*)mono_object_unbox (res);
12593 * mono_reflection_type_get_type:
12594 * @reftype: the System.Type object
12596 * Returns the MonoType* associated with the C# System.Type object @reftype.
12599 mono_reflection_type_get_type (MonoReflectionType *reftype)
12601 g_assert (reftype);
12603 return mono_reflection_type_get_handle (reftype);