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;
1547 if (!mb->override_method)
1550 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1552 alloc_table (table, table->rows);
1553 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1554 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1555 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1557 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1558 switch (mono_metadata_token_table (tok)) {
1559 case MONO_TABLE_MEMBERREF:
1560 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1562 case MONO_TABLE_METHOD:
1563 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1566 g_assert_not_reached ();
1568 values [MONO_METHODIMPL_DECLARATION] = tok;
1571 #ifndef DISABLE_REFLECTION_EMIT
1573 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1575 MonoDynamicTable *table;
1577 ReflectionMethodBuilder rmb;
1580 reflection_methodbuilder_from_method_builder (&rmb, mb);
1582 mono_image_basic_method (&rmb, assembly);
1583 mb->table_idx = *rmb.table_idx;
1585 if (mb->dll) { /* It's a P/Invoke method */
1587 /* map CharSet values to on-disk values */
1588 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1589 int extra_flags = mb->extra_flags;
1590 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1592 alloc_table (table, table->rows);
1593 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1595 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1596 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1598 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1600 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1601 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1602 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1603 table = &assembly->tables [MONO_TABLE_MODULEREF];
1605 alloc_table (table, table->rows);
1606 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1607 values [MONO_IMPLMAP_SCOPE] = table->rows;
1611 if (mb->generic_params) {
1612 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1613 table->rows += mono_array_length (mb->generic_params);
1614 alloc_table (table, table->rows);
1615 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1616 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1618 mono_image_get_generic_param_info (
1619 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1626 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1628 ReflectionMethodBuilder rmb;
1630 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1632 mono_image_basic_method (&rmb, assembly);
1633 mb->table_idx = *rmb.table_idx;
1638 type_get_fully_qualified_name (MonoType *type)
1640 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1644 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1648 klass = mono_class_from_mono_type (type);
1650 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1651 ta = klass->image->assembly;
1652 if (ta->dynamic || (ta == ass)) {
1653 if (klass->generic_class || klass->generic_container)
1654 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1655 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1657 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1660 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1663 #ifndef DISABLE_REFLECTION_EMIT
1664 /*field_image is the image to which the eventual custom mods have been encoded against*/
1666 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1669 guint32 idx, i, token;
1671 if (!assembly->save)
1674 sigbuffer_init (&buf, 32);
1676 sigbuffer_add_value (&buf, 0x06);
1677 /* encode custom attributes before the type */
1678 if (type->num_mods) {
1679 for (i = 0; i < type->num_mods; ++i) {
1681 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1683 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1685 token = type->modifiers [i].token;
1688 if (type->modifiers [i].required)
1689 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1691 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1693 sigbuffer_add_value (&buf, token);
1696 encode_type (assembly, type, &buf);
1697 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1698 sigbuffer_free (&buf);
1704 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1708 guint32 typespec = 0;
1712 init_type_builder_generics (fb->type);
1714 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1715 class = mono_class_from_mono_type (type);
1717 sigbuffer_init (&buf, 32);
1719 sigbuffer_add_value (&buf, 0x06);
1720 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721 /* encode custom attributes before the type */
1723 if (class->generic_container)
1724 typespec = create_typespec (assembly, type);
1727 MonoGenericClass *gclass;
1728 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1729 encode_generic_class (assembly, gclass, &buf);
1731 encode_type (assembly, type, &buf);
1733 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1734 sigbuffer_free (&buf);
1739 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1740 char blob_size [64];
1741 char *b = blob_size;
1744 guint32 idx = 0, len = 0, dummy = 0;
1746 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1747 guint32 fpa_double [2];
1752 p = buf = g_malloc (64);
1754 *ret_type = MONO_TYPE_CLASS;
1756 box_val = (char*)&dummy;
1758 box_val = ((char*)val) + sizeof (MonoObject);
1759 *ret_type = val->vtable->klass->byval_arg.type;
1762 switch (*ret_type) {
1763 case MONO_TYPE_BOOLEAN:
1768 case MONO_TYPE_CHAR:
1785 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1786 fpa_p = (guint32*)box_val;
1787 fpa_double [0] = fpa_p [1];
1788 fpa_double [1] = fpa_p [0];
1789 box_val = (char*)fpa_double;
1793 case MONO_TYPE_VALUETYPE: {
1794 MonoClass *klass = val->vtable->klass;
1796 if (klass->enumtype) {
1797 *ret_type = mono_class_enum_basetype (klass)->type;
1799 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1802 g_error ("we can't encode valuetypes, we should have never reached this line");
1805 case MONO_TYPE_CLASS:
1807 case MONO_TYPE_STRING: {
1808 MonoString *str = (MonoString*)val;
1809 /* there is no signature */
1810 len = str->length * 2;
1811 mono_metadata_encode_value (len, b, &b);
1812 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1814 char *swapped = g_malloc (2 * mono_string_length (str));
1815 const char *p = (const char*)mono_string_chars (str);
1817 swap_with_size (swapped, p, 2, mono_string_length (str));
1818 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1822 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1828 case MONO_TYPE_GENERICINST:
1829 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1832 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1835 /* there is no signature */
1836 mono_metadata_encode_value (len, b, &b);
1837 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1838 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1839 swap_with_size (blob_size, box_val, len, 1);
1840 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1842 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1850 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1855 sigbuffer_init (&buf, 32);
1857 sigbuffer_add_value (&buf, minfo->type);
1859 switch (minfo->type) {
1860 case MONO_NATIVE_BYVALTSTR:
1861 case MONO_NATIVE_BYVALARRAY:
1862 sigbuffer_add_value (&buf, minfo->count);
1864 case MONO_NATIVE_LPARRAY:
1865 if (minfo->eltype || minfo->has_size) {
1866 sigbuffer_add_value (&buf, minfo->eltype);
1867 if (minfo->has_size) {
1868 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1869 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1871 /* LAMESPEC: ElemMult is undocumented */
1872 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1876 case MONO_NATIVE_SAFEARRAY:
1878 sigbuffer_add_value (&buf, minfo->eltype);
1880 case MONO_NATIVE_CUSTOM:
1882 str = mono_string_to_utf8 (minfo->guid);
1884 sigbuffer_add_value (&buf, len);
1885 sigbuffer_add_mem (&buf, str, len);
1888 sigbuffer_add_value (&buf, 0);
1890 /* native type name */
1891 sigbuffer_add_value (&buf, 0);
1892 /* custom marshaler type name */
1893 if (minfo->marshaltype || minfo->marshaltyperef) {
1894 if (minfo->marshaltyperef)
1895 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1897 str = mono_string_to_utf8 (minfo->marshaltype);
1899 sigbuffer_add_value (&buf, len);
1900 sigbuffer_add_mem (&buf, str, len);
1903 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1904 sigbuffer_add_value (&buf, 0);
1906 if (minfo->mcookie) {
1907 str = mono_string_to_utf8 (minfo->mcookie);
1909 sigbuffer_add_value (&buf, len);
1910 sigbuffer_add_mem (&buf, str, len);
1913 sigbuffer_add_value (&buf, 0);
1919 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1920 sigbuffer_free (&buf);
1925 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1927 MonoDynamicTable *table;
1930 /* maybe this fixup should be done in the C# code */
1931 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1932 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1933 table = &assembly->tables [MONO_TABLE_FIELD];
1934 fb->table_idx = table->next_idx ++;
1935 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1936 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1937 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1938 values [MONO_FIELD_FLAGS] = fb->attrs;
1939 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1941 if (fb->offset != -1) {
1942 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1944 alloc_table (table, table->rows);
1945 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1946 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1947 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1949 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1950 guint32 field_type = 0;
1951 table = &assembly->tables [MONO_TABLE_CONSTANT];
1953 alloc_table (table, table->rows);
1954 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1955 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1956 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1957 values [MONO_CONSTANT_TYPE] = field_type;
1958 values [MONO_CONSTANT_PADDING] = 0;
1960 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1962 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1964 alloc_table (table, table->rows);
1965 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1966 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1968 * We store it in the code section because it's simpler for now.
1971 if (mono_array_length (fb->rva_data) >= 10)
1972 stream_data_align (&assembly->code);
1973 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1975 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1976 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1978 if (fb->marshal_info) {
1979 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1981 alloc_table (table, table->rows);
1982 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1983 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1984 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1989 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1992 guint32 nparams = 0;
1993 MonoReflectionMethodBuilder *mb = fb->get_method;
1994 MonoReflectionMethodBuilder *smb = fb->set_method;
1997 if (mb && mb->parameters)
1998 nparams = mono_array_length (mb->parameters);
1999 if (!mb && smb && smb->parameters)
2000 nparams = mono_array_length (smb->parameters) - 1;
2001 sigbuffer_init (&buf, 32);
2002 if (fb->call_conv & 0x20)
2003 sigbuffer_add_byte (&buf, 0x28);
2005 sigbuffer_add_byte (&buf, 0x08);
2006 sigbuffer_add_value (&buf, nparams);
2008 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2009 for (i = 0; i < nparams; ++i) {
2010 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2011 encode_reflection_type (assembly, pt, &buf);
2013 } else if (smb && smb->parameters) {
2014 /* the property type is the last param */
2015 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2016 for (i = 0; i < nparams; ++i) {
2017 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2018 encode_reflection_type (assembly, pt, &buf);
2021 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2024 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2025 sigbuffer_free (&buf);
2030 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2032 MonoDynamicTable *table;
2034 guint num_methods = 0;
2038 * we need to set things in the following tables:
2039 * PROPERTYMAP (info already filled in _get_type_info ())
2040 * PROPERTY (rows already preallocated in _get_type_info ())
2041 * METHOD (method info already done with the generic method code)
2045 table = &assembly->tables [MONO_TABLE_PROPERTY];
2046 pb->table_idx = table->next_idx ++;
2047 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2048 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2049 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2050 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2052 /* FIXME: we still don't handle 'other' methods */
2053 if (pb->get_method) num_methods ++;
2054 if (pb->set_method) num_methods ++;
2056 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2057 table->rows += num_methods;
2058 alloc_table (table, table->rows);
2060 if (pb->get_method) {
2061 semaidx = table->next_idx ++;
2062 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2063 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2064 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2065 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2067 if (pb->set_method) {
2068 semaidx = table->next_idx ++;
2069 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2070 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2071 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2072 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2074 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2075 guint32 field_type = 0;
2076 table = &assembly->tables [MONO_TABLE_CONSTANT];
2078 alloc_table (table, table->rows);
2079 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2080 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2081 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2082 values [MONO_CONSTANT_TYPE] = field_type;
2083 values [MONO_CONSTANT_PADDING] = 0;
2088 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2090 MonoDynamicTable *table;
2092 guint num_methods = 0;
2096 * we need to set things in the following tables:
2097 * EVENTMAP (info already filled in _get_type_info ())
2098 * EVENT (rows already preallocated in _get_type_info ())
2099 * METHOD (method info already done with the generic method code)
2102 table = &assembly->tables [MONO_TABLE_EVENT];
2103 eb->table_idx = table->next_idx ++;
2104 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2105 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2106 values [MONO_EVENT_FLAGS] = eb->attrs;
2107 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2110 * FIXME: we still don't handle 'other' methods
2112 if (eb->add_method) num_methods ++;
2113 if (eb->remove_method) num_methods ++;
2114 if (eb->raise_method) num_methods ++;
2116 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2117 table->rows += num_methods;
2118 alloc_table (table, table->rows);
2120 if (eb->add_method) {
2121 semaidx = table->next_idx ++;
2122 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2123 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2124 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2125 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2127 if (eb->remove_method) {
2128 semaidx = table->next_idx ++;
2129 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2130 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2131 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2132 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2134 if (eb->raise_method) {
2135 semaidx = table->next_idx ++;
2136 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2137 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2138 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2139 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2144 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2146 MonoDynamicTable *table;
2147 guint32 num_constraints, i;
2151 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2152 num_constraints = gparam->iface_constraints ?
2153 mono_array_length (gparam->iface_constraints) : 0;
2154 table->rows += num_constraints;
2155 if (gparam->base_type)
2157 alloc_table (table, table->rows);
2159 if (gparam->base_type) {
2160 table_idx = table->next_idx ++;
2161 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2163 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2164 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2165 assembly, mono_reflection_type_get_handle (gparam->base_type));
2168 for (i = 0; i < num_constraints; i++) {
2169 MonoReflectionType *constraint = mono_array_get (
2170 gparam->iface_constraints, gpointer, i);
2172 table_idx = table->next_idx ++;
2173 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2175 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177 assembly, mono_reflection_type_get_handle (constraint));
2182 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2184 GenericParamTableEntry *entry;
2187 * The GenericParam table must be sorted according to the `owner' field.
2188 * We need to do this sorting prior to writing the GenericParamConstraint
2189 * table, since we have to use the final GenericParam table indices there
2190 * and they must also be sorted.
2193 entry = g_new0 (GenericParamTableEntry, 1);
2194 entry->owner = owner;
2195 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2196 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2197 entry->gparam = gparam;
2199 g_ptr_array_add (assembly->gen_params, entry);
2203 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2205 MonoDynamicTable *table;
2206 MonoGenericParam *param;
2210 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2211 table_idx = table->next_idx ++;
2212 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2214 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2216 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2217 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2218 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2219 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2221 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2223 encode_constraints (entry->gparam, table_idx, assembly);
2227 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2229 MonoDynamicTable *table;
2232 guint32 cols [MONO_ASSEMBLY_SIZE];
2236 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2239 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2240 table = &assembly->tables [MONO_TABLE_MODULEREF];
2241 token = table->next_idx ++;
2243 alloc_table (table, table->rows);
2244 values = table->values + token * MONO_MODULEREF_SIZE;
2245 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2247 token <<= MONO_RESOLTION_SCOPE_BITS;
2248 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2249 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2254 if (image->assembly->dynamic)
2256 memset (cols, 0, sizeof (cols));
2258 /* image->assembly->image is the manifest module */
2259 image = image->assembly->image;
2260 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2263 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2264 token = table->next_idx ++;
2266 alloc_table (table, table->rows);
2267 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2268 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2269 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2270 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2271 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2272 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2273 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2274 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2275 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2277 if (strcmp ("", image->assembly->aname.culture)) {
2278 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2279 image->assembly->aname.culture);
2282 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2283 guchar pubtoken [9];
2285 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2286 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2288 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2290 token <<= MONO_RESOLTION_SCOPE_BITS;
2291 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2292 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2297 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2299 MonoDynamicTable *table;
2304 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2307 sigbuffer_init (&buf, 32);
2308 switch (type->type) {
2309 case MONO_TYPE_FNPTR:
2311 case MONO_TYPE_SZARRAY:
2312 case MONO_TYPE_ARRAY:
2314 case MONO_TYPE_MVAR:
2315 case MONO_TYPE_GENERICINST:
2316 encode_type (assembly, type, &buf);
2318 case MONO_TYPE_CLASS:
2319 case MONO_TYPE_VALUETYPE: {
2320 MonoClass *k = mono_class_from_mono_type (type);
2321 if (!k || !k->generic_container) {
2322 sigbuffer_free (&buf);
2325 encode_type (assembly, type, &buf);
2329 sigbuffer_free (&buf);
2333 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2334 if (assembly->save) {
2335 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2336 alloc_table (table, table->rows + 1);
2337 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2338 values [MONO_TYPESPEC_SIGNATURE] = token;
2340 sigbuffer_free (&buf);
2342 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2343 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2349 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2351 MonoDynamicTable *table;
2353 guint32 token, scope, enclosing;
2356 /* if the type requires a typespec, we must try that first*/
2357 if (try_typespec && (token = create_typespec (assembly, type)))
2359 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2362 klass = mono_class_from_mono_type (type);
2364 klass = mono_class_from_mono_type (type);
2367 * If it's in the same module and not a generic type parameter:
2369 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2370 (type->type != MONO_TYPE_MVAR)) {
2371 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2372 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2373 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2377 if (klass->nested_in) {
2378 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2379 /* get the typeref idx of the enclosing type */
2380 enclosing >>= MONO_TYPEDEFORREF_BITS;
2381 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2383 scope = resolution_scope_from_image (assembly, klass->image);
2385 table = &assembly->tables [MONO_TABLE_TYPEREF];
2386 if (assembly->save) {
2387 alloc_table (table, table->rows + 1);
2388 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2389 values [MONO_TYPEREF_SCOPE] = scope;
2390 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2391 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2393 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2394 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2396 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2401 * Despite the name, we handle also TypeSpec (with the above helper).
2404 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2406 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2409 #ifndef DISABLE_REFLECTION_EMIT
2411 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2413 MonoDynamicTable *table;
2415 guint32 token, pclass;
2417 switch (parent & MONO_TYPEDEFORREF_MASK) {
2418 case MONO_TYPEDEFORREF_TYPEREF:
2419 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2421 case MONO_TYPEDEFORREF_TYPESPEC:
2422 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2424 case MONO_TYPEDEFORREF_TYPEDEF:
2425 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2428 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2431 /* extract the index */
2432 parent >>= MONO_TYPEDEFORREF_BITS;
2434 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2436 if (assembly->save) {
2437 alloc_table (table, table->rows + 1);
2438 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2439 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2440 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2441 values [MONO_MEMBERREF_SIGNATURE] = sig;
2444 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2451 * Insert a memberef row into the metadata: the token that point to the memberref
2452 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2453 * mono_image_get_fieldref_token()).
2454 * The sig param is an index to an already built signature.
2457 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2459 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2460 return mono_image_add_memberef_row (assembly, parent, name, sig);
2465 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2468 MonoMethodSignature *sig;
2470 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2472 if (create_typespec) {
2473 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2478 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2479 if (token && !create_typespec)
2482 g_assert (!method->is_inflated);
2485 * A methodref signature can't contain an unmanaged calling convention.
2487 sig = mono_metadata_signature_dup (mono_method_signature (method));
2488 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2489 sig->call_convention = MONO_CALL_DEFAULT;
2490 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2491 method->name, method_encode_signature (assembly, sig));
2493 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2496 if (create_typespec) {
2497 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2498 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2499 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2501 if (assembly->save) {
2504 alloc_table (table, table->rows + 1);
2505 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2506 values [MONO_METHODSPEC_METHOD] = token;
2507 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2510 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2512 /*methodspec and memberef tokens are diferent, */
2513 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2520 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2522 guint32 token, parent, sig;
2523 ReflectionMethodBuilder rmb;
2525 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2527 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2531 name = mono_string_to_utf8 (method->name);
2532 reflection_methodbuilder_from_method_builder (&rmb, method);
2535 * A methodref signature can't contain an unmanaged calling convention.
2536 * Since some flags are encoded as part of call_conv, we need to check against it.
2538 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2539 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2541 sig = method_builder_encode_signature (assembly, &rmb);
2543 if (tb->generic_params)
2544 parent = create_generic_typespec (assembly, tb);
2546 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2548 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2551 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2556 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2557 const gchar *name, guint32 sig)
2559 MonoDynamicTable *table;
2563 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2565 if (assembly->save) {
2566 alloc_table (table, table->rows + 1);
2567 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2568 values [MONO_MEMBERREF_CLASS] = original;
2569 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2570 values [MONO_MEMBERREF_SIGNATURE] = sig;
2573 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2580 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2584 guint32 nparams = mono_array_length (mb->generic_params);
2587 if (!assembly->save)
2590 sigbuffer_init (&buf, 32);
2592 sigbuffer_add_value (&buf, 0xa);
2593 sigbuffer_add_value (&buf, nparams);
2595 for (i = 0; i < nparams; i++) {
2596 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2597 sigbuffer_add_value (&buf, i);
2600 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2601 sigbuffer_free (&buf);
2606 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2608 MonoDynamicTable *table;
2610 guint32 token, mtoken = 0;
2612 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2616 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2618 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2619 switch (mono_metadata_token_table (mtoken)) {
2620 case MONO_TABLE_MEMBERREF:
2621 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2623 case MONO_TABLE_METHOD:
2624 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2627 g_assert_not_reached ();
2630 if (assembly->save) {
2631 alloc_table (table, table->rows + 1);
2632 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2633 values [MONO_METHODSPEC_METHOD] = mtoken;
2634 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2637 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2640 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2645 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2649 if (mb->generic_params && create_methodspec)
2650 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2652 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2656 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2657 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2662 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2664 guint32 token, parent, sig;
2665 ReflectionMethodBuilder rmb;
2667 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2669 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2673 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2675 if (tb->generic_params)
2676 parent = create_generic_typespec (assembly, tb);
2678 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2680 name = mono_string_to_utf8 (rmb.name);
2681 sig = method_builder_encode_signature (assembly, &rmb);
2683 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2686 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2692 is_field_on_inst (MonoClassField *field)
2694 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2698 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2701 get_field_on_inst_generic_type (MonoClassField *field)
2703 MonoClass *class, *gtd;
2704 MonoDynamicGenericClass *dgclass;
2707 g_assert (is_field_on_inst (field));
2709 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2711 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2712 field_index = field - dgclass->fields;
2713 return dgclass->field_generic_types [field_index];
2716 class = field->parent;
2717 gtd = class->generic_class->container_class;
2719 if (field >= class->fields && field - class->fields < class->field.count) {
2720 field_index = field - class->fields;
2721 return gtd->fields [field_index].type;
2724 g_assert_not_reached ();
2728 #ifndef DISABLE_REFLECTION_EMIT
2730 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2736 g_assert (field->parent);
2738 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2742 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2743 int index = field - field->parent->fields;
2744 type = field->parent->generic_class->container_class->fields [index].type;
2746 if (is_field_on_inst (field))
2747 type = get_field_on_inst_generic_type (field);
2749 type = mono_field_get_type (field);
2751 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2752 mono_field_get_name (field),
2753 fieldref_encode_signature (assembly, field->parent->image, type));
2754 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2759 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2763 MonoGenericClass *gclass;
2764 MonoDynamicGenericClass *dgclass;
2768 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2771 if (is_sre_field_builder (mono_object_class (f->fb))) {
2772 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2773 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2774 klass = mono_class_from_mono_type (type);
2775 gclass = type->data.generic_class;
2776 g_assert (gclass->is_dynamic);
2777 dgclass = (MonoDynamicGenericClass *) gclass;
2779 name = mono_string_to_utf8 (fb->name);
2780 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2781 field_encode_signature (assembly, fb));
2783 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2785 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2787 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2788 klass = mono_class_from_mono_type (type);
2790 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2791 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2793 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2794 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2797 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2802 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2806 MonoGenericClass *gclass;
2809 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2811 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2815 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2816 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2817 MonoDynamicGenericClass *dgclass;
2818 ReflectionMethodBuilder rmb;
2821 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2822 klass = mono_class_from_mono_type (type);
2824 gclass = type->data.generic_class;
2825 g_assert (gclass->is_dynamic);
2826 dgclass = (MonoDynamicGenericClass *) gclass;
2828 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2830 name = mono_string_to_utf8 (rmb.name);
2832 sig = method_builder_encode_signature (assembly, &rmb);
2834 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2836 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2837 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2839 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2840 klass = mono_class_from_mono_type (type);
2842 sig = method_encode_signature (assembly, mono_method_signature (mm));
2843 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2845 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2846 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2850 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2855 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2858 MonoGenericContext tmp_context;
2859 MonoType **type_argv;
2860 MonoGenericInst *ginst;
2861 MonoMethod *method, *inflated;
2864 init_type_builder_generics ((MonoObject*)m->inst);
2866 method = inflate_method (m->inst, (MonoObject*)m->mb);
2868 klass = method->klass;
2870 if (m->method_args == NULL)
2873 if (method->is_inflated)
2874 method = ((MonoMethodInflated *) method)->declaring;
2876 count = mono_array_length (m->method_args);
2878 type_argv = g_new0 (MonoType *, count);
2879 for (i = 0; i < count; i++) {
2880 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2881 type_argv [i] = mono_reflection_type_get_handle (garg);
2883 ginst = mono_metadata_get_generic_inst (count, type_argv);
2886 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2887 tmp_context.method_inst = ginst;
2889 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2894 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2896 guint32 sig, token = 0;
2900 if (m->method_args) {
2901 MonoMethod *inflated;
2903 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2904 if (create_methodspec)
2905 token = mono_image_get_methodspec_token (assembly, inflated);
2907 token = mono_image_get_inflated_method_token (assembly, inflated);
2911 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2915 if (is_sre_method_builder (mono_object_class (m->mb))) {
2916 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2917 MonoGenericClass *gclass;
2918 ReflectionMethodBuilder rmb;
2921 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2922 klass = mono_class_from_mono_type (type);
2923 gclass = type->data.generic_class;
2924 g_assert (gclass->is_dynamic);
2926 reflection_methodbuilder_from_method_builder (&rmb, mb);
2928 name = mono_string_to_utf8 (rmb.name);
2930 sig = method_builder_encode_signature (assembly, &rmb);
2932 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2934 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2935 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2937 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2938 klass = mono_class_from_mono_type (type);
2940 sig = method_encode_signature (assembly, mono_method_signature (mm));
2941 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2943 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2944 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2947 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2952 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2956 guint32 nparams = context->method_inst->type_argc;
2959 if (!assembly->save)
2962 sigbuffer_init (&buf, 32);
2964 * FIXME: vararg, explicit_this, differenc call_conv values...
2966 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2967 sigbuffer_add_value (&buf, nparams);
2969 for (i = 0; i < nparams; i++)
2970 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2972 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2973 sigbuffer_free (&buf);
2978 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2980 MonoDynamicTable *table;
2982 guint32 token, mtoken = 0, sig;
2983 MonoMethodInflated *imethod;
2984 MonoMethod *declaring;
2986 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2988 g_assert (method->is_inflated);
2989 imethod = (MonoMethodInflated *) method;
2990 declaring = imethod->declaring;
2992 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2993 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2995 if (!mono_method_signature (declaring)->generic_param_count)
2998 switch (mono_metadata_token_table (mtoken)) {
2999 case MONO_TABLE_MEMBERREF:
3000 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3002 case MONO_TABLE_METHOD:
3003 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3006 g_assert_not_reached ();
3009 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3011 if (assembly->save) {
3012 alloc_table (table, table->rows + 1);
3013 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3014 values [MONO_METHODSPEC_METHOD] = mtoken;
3015 values [MONO_METHODSPEC_SIGNATURE] = sig;
3018 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3025 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3027 MonoMethodInflated *imethod;
3030 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3034 g_assert (method->is_inflated);
3035 imethod = (MonoMethodInflated *) method;
3037 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3038 token = method_encode_methodspec (assembly, method);
3040 guint32 sig = method_encode_signature (
3041 assembly, mono_method_signature (imethod->declaring));
3042 token = mono_image_get_memberref_token (
3043 assembly, &method->klass->byval_arg, method->name, sig);
3046 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3051 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3053 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3056 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3057 token = mono_image_get_memberref_token (
3058 assembly, &m->klass->byval_arg, m->name, sig);
3064 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3066 MonoDynamicTable *table;
3075 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3076 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3077 * Because of this, we must not insert it into the `typeref' hash table.
3079 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3080 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3084 sigbuffer_init (&buf, 32);
3086 g_assert (tb->generic_params);
3087 klass = mono_class_from_mono_type (type);
3089 if (tb->generic_container)
3090 mono_reflection_create_generic_class (tb);
3092 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3093 g_assert (klass->generic_container);
3094 sigbuffer_add_value (&buf, klass->byval_arg.type);
3095 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3097 count = mono_array_length (tb->generic_params);
3098 sigbuffer_add_value (&buf, count);
3099 for (i = 0; i < count; i++) {
3100 MonoReflectionGenericParam *gparam;
3102 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3104 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3107 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3109 if (assembly->save) {
3110 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3111 alloc_table (table, table->rows + 1);
3112 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3113 values [MONO_TYPESPEC_SIGNATURE] = token;
3115 sigbuffer_free (&buf);
3117 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3118 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3124 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3127 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3129 int i, count, len, pos;
3134 count += mono_array_length (modreq);
3136 count += mono_array_length (modopt);
3139 return mono_metadata_type_dup (NULL, type);
3141 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3143 memcpy (t, type, MONO_SIZEOF_TYPE);
3145 t->num_mods = count;
3148 for (i = 0; i < mono_array_length (modreq); ++i) {
3149 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3150 t->modifiers [pos].required = 1;
3151 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3156 for (i = 0; i < mono_array_length (modopt); ++i) {
3157 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3158 t->modifiers [pos].required = 0;
3159 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3168 init_type_builder_generics (MonoObject *type)
3170 MonoReflectionTypeBuilder *tb;
3172 if (!is_sre_type_builder(mono_object_class (type)))
3174 tb = (MonoReflectionTypeBuilder *)type;
3176 if (tb && tb->generic_container)
3177 mono_reflection_create_generic_class (tb);
3181 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3183 MonoDynamicTable *table;
3185 MonoType *custom = NULL, *type;
3187 guint32 token, pclass, parent, sig;
3190 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3194 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3195 name = mono_string_to_utf8 (fb->name);
3197 /*FIXME this is one more layer of ugliness due how types are created.*/
3198 init_type_builder_generics (fb->type);
3200 /* fb->type does not include the custom modifiers */
3201 /* FIXME: We should do this in one place when a fieldbuilder is created */
3202 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3203 if (fb->modreq || fb->modopt)
3204 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3206 sig = fieldref_encode_signature (assembly, NULL, type);
3209 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3210 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3212 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3213 parent >>= MONO_TYPEDEFORREF_BITS;
3215 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3217 if (assembly->save) {
3218 alloc_table (table, table->rows + 1);
3219 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3220 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3221 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3222 values [MONO_MEMBERREF_SIGNATURE] = sig;
3225 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3227 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3233 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3240 if (!assembly->save)
3243 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3244 g_assert (helper->type == 2);
3246 if (helper->arguments)
3247 nargs = mono_array_length (helper->arguments);
3251 size = 10 + (nargs * 10);
3253 sigbuffer_init (&buf, 32);
3255 /* Encode calling convention */
3256 /* Change Any to Standard */
3257 if ((helper->call_conv & 0x03) == 0x03)
3258 helper->call_conv = 0x01;
3259 /* explicit_this implies has_this */
3260 if (helper->call_conv & 0x40)
3261 helper->call_conv &= 0x20;
3263 if (helper->call_conv == 0) { /* Unmanaged */
3264 idx = helper->unmanaged_call_conv - 1;
3267 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3268 if (helper->call_conv & 0x02) /* varargs */
3272 sigbuffer_add_byte (&buf, idx);
3273 sigbuffer_add_value (&buf, nargs);
3274 encode_reflection_type (assembly, helper->return_type, &buf);
3275 for (i = 0; i < nargs; ++i) {
3276 MonoArray *modreqs = NULL;
3277 MonoArray *modopts = NULL;
3278 MonoReflectionType *pt;
3280 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3281 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3282 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3283 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3285 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3286 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3287 encode_reflection_type (assembly, pt, &buf);
3289 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3290 sigbuffer_free (&buf);
3296 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3299 MonoDynamicTable *table;
3302 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3303 idx = table->next_idx ++;
3305 alloc_table (table, table->rows);
3306 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3308 values [MONO_STAND_ALONE_SIGNATURE] =
3309 mono_reflection_encode_sighelper (assembly, helper);
3315 reflection_cc_to_file (int call_conv) {
3316 switch (call_conv & 0x3) {
3318 case 1: return MONO_CALL_DEFAULT;
3319 case 2: return MONO_CALL_VARARG;
3321 g_assert_not_reached ();
3325 #endif /* !DISABLE_REFLECTION_EMIT */
3329 MonoMethodSignature *sig;
3334 #ifndef DISABLE_REFLECTION_EMIT
3336 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3341 MonoMethodSignature *sig;
3345 name = mono_string_to_utf8 (m->name);
3346 nparams = mono_array_length (m->parameters);
3347 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3349 sig->sentinelpos = -1;
3350 sig->call_convention = reflection_cc_to_file (m->call_conv);
3351 sig->param_count = nparams;
3352 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3353 mtype = mono_reflection_type_get_handle (m->parent);
3354 for (i = 0; i < nparams; ++i)
3355 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3357 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3359 if (strcmp (name, am->name) == 0 &&
3360 mono_metadata_type_equal (am->parent, mtype) &&
3361 mono_metadata_signature_equal (am->sig, sig)) {
3364 m->table_idx = am->token & 0xffffff;
3368 am = g_new0 (ArrayMethod, 1);
3372 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3373 method_encode_signature (assembly, sig));
3374 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3375 m->table_idx = am->token & 0xffffff;
3380 * Insert into the metadata tables all the info about the TypeBuilder tb.
3381 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3384 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3386 MonoDynamicTable *table;
3388 int i, is_object = 0, is_system = 0;
3391 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3392 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3393 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3394 n = mono_string_to_utf8 (tb->name);
3395 if (strcmp (n, "Object") == 0)
3397 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3399 n = mono_string_to_utf8 (tb->nspace);
3400 if (strcmp (n, "System") == 0)
3402 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3404 if (tb->parent && !(is_system && is_object) &&
3405 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3406 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3408 values [MONO_TYPEDEF_EXTENDS] = 0;
3410 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3411 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3414 * if we have explicitlayout or sequentiallayouts, output data in the
3415 * ClassLayout table.
3417 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3418 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3419 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3421 alloc_table (table, table->rows);
3422 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3423 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3424 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3425 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3428 /* handle interfaces */
3429 if (tb->interfaces) {
3430 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3432 table->rows += mono_array_length (tb->interfaces);
3433 alloc_table (table, table->rows);
3434 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3435 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3436 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3437 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3438 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3439 values += MONO_INTERFACEIMPL_SIZE;
3445 table = &assembly->tables [MONO_TABLE_FIELD];
3446 table->rows += tb->num_fields;
3447 alloc_table (table, table->rows);
3448 for (i = 0; i < tb->num_fields; ++i)
3449 mono_image_get_field_info (
3450 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3453 /* handle constructors */
3455 table = &assembly->tables [MONO_TABLE_METHOD];
3456 table->rows += mono_array_length (tb->ctors);
3457 alloc_table (table, table->rows);
3458 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3459 mono_image_get_ctor_info (domain,
3460 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3463 /* handle methods */
3465 table = &assembly->tables [MONO_TABLE_METHOD];
3466 table->rows += tb->num_methods;
3467 alloc_table (table, table->rows);
3468 for (i = 0; i < tb->num_methods; ++i)
3469 mono_image_get_method_info (
3470 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3473 /* Do the same with properties etc.. */
3474 if (tb->events && mono_array_length (tb->events)) {
3475 table = &assembly->tables [MONO_TABLE_EVENT];
3476 table->rows += mono_array_length (tb->events);
3477 alloc_table (table, table->rows);
3478 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3480 alloc_table (table, table->rows);
3481 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3482 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3483 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3484 for (i = 0; i < mono_array_length (tb->events); ++i)
3485 mono_image_get_event_info (
3486 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3488 if (tb->properties && mono_array_length (tb->properties)) {
3489 table = &assembly->tables [MONO_TABLE_PROPERTY];
3490 table->rows += mono_array_length (tb->properties);
3491 alloc_table (table, table->rows);
3492 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3494 alloc_table (table, table->rows);
3495 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3496 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3497 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3498 for (i = 0; i < mono_array_length (tb->properties); ++i)
3499 mono_image_get_property_info (
3500 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3503 /* handle generic parameters */
3504 if (tb->generic_params) {
3505 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3506 table->rows += mono_array_length (tb->generic_params);
3507 alloc_table (table, table->rows);
3508 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3509 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3511 mono_image_get_generic_param_info (
3512 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3516 mono_image_add_decl_security (assembly,
3517 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3520 MonoDynamicTable *ntable;
3522 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3523 ntable->rows += mono_array_length (tb->subtypes);
3524 alloc_table (ntable, ntable->rows);
3525 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3527 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3528 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3530 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3531 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3532 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3533 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3534 mono_string_to_utf8 (tb->name), tb->table_idx,
3535 ntable->next_idx, ntable->rows);*/
3536 values += MONO_NESTED_CLASS_SIZE;
3544 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3548 mono_ptr_array_append (*types, type);
3550 if (!type->subtypes)
3553 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3554 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3555 collect_types (types, subtype);
3560 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3562 if ((*type1)->table_idx < (*type2)->table_idx)
3565 if ((*type1)->table_idx > (*type2)->table_idx)
3572 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3577 for (i = 0; i < mono_array_length (pinfo); ++i) {
3578 MonoReflectionParamBuilder *pb;
3579 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3582 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3587 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3590 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3592 for (i = 0; i < tb->num_fields; ++i) {
3593 MonoReflectionFieldBuilder* fb;
3594 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3595 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3599 for (i = 0; i < mono_array_length (tb->events); ++i) {
3600 MonoReflectionEventBuilder* eb;
3601 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3602 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3605 if (tb->properties) {
3606 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3607 MonoReflectionPropertyBuilder* pb;
3608 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3609 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3613 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3614 MonoReflectionCtorBuilder* cb;
3615 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3616 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3617 params_add_cattrs (assembly, cb->pinfo);
3622 for (i = 0; i < tb->num_methods; ++i) {
3623 MonoReflectionMethodBuilder* mb;
3624 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3625 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3626 params_add_cattrs (assembly, mb->pinfo);
3631 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3632 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3637 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3641 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3643 if (moduleb->global_methods) {
3644 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3645 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3646 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3647 params_add_cattrs (assembly, mb->pinfo);
3651 if (moduleb->global_fields) {
3652 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3653 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3654 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3658 if (moduleb->types) {
3659 for (i = 0; i < moduleb->num_types; ++i)
3660 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3665 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3667 MonoDynamicTable *table;
3671 char *b = blob_size;
3674 table = &assembly->tables [MONO_TABLE_FILE];
3676 alloc_table (table, table->rows);
3677 values = table->values + table->next_idx * MONO_FILE_SIZE;
3678 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3679 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3680 if (module->image->dynamic) {
3681 /* This depends on the fact that the main module is emitted last */
3682 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3683 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3686 path = g_strdup (module->image->name);
3688 mono_sha1_get_digest_from_file (path, hash);
3691 mono_metadata_encode_value (20, b, &b);
3692 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3693 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3698 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3700 MonoDynamicTable *table;
3703 table = &assembly->tables [MONO_TABLE_MODULE];
3704 mb->table_idx = table->next_idx ++;
3705 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3706 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3709 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3710 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3711 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3712 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3716 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3717 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3719 MonoDynamicTable *table;
3723 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3724 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3727 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3729 alloc_table (table, table->rows);
3730 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3732 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3733 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3734 if (klass->nested_in)
3735 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3737 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3738 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3739 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3741 res = table->next_idx;
3745 /* Emit nested types */
3746 if (klass->ext && klass->ext->nested_classes) {
3749 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3750 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3757 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3758 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3763 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3765 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3767 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3768 parent_index, assembly);
3772 * We need to do this ourselves since klass->nested_classes is not set up.
3775 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3776 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3781 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3782 guint32 module_index, MonoDynamicImage *assembly)
3784 MonoImage *image = module->image;
3788 t = &image->tables [MONO_TABLE_TYPEDEF];
3790 for (i = 0; i < t->rows; ++i) {
3791 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3793 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3794 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3799 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3801 MonoDynamicTable *table;
3803 guint32 scope, scope_idx, impl, current_idx;
3804 gboolean forwarder = TRUE;
3805 gpointer iter = NULL;
3808 if (klass->nested_in) {
3809 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3812 scope = resolution_scope_from_image (assembly, klass->image);
3813 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3814 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3815 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3818 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3821 alloc_table (table, table->rows);
3822 current_idx = table->next_idx;
3823 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3825 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3826 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3827 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3828 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3829 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3833 while ((nested = mono_class_get_nested_types (klass, &iter)))
3834 add_exported_type (assemblyb, assembly, nested, current_idx);
3838 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3843 if (!assemblyb->type_forwarders)
3846 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3847 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3852 type = mono_reflection_type_get_handle (t);
3855 klass = mono_class_from_mono_type (type);
3857 add_exported_type (assemblyb, assembly, klass, 0);
3861 #define align_pointer(base,p)\
3863 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3865 (p) += 4 - (__diff & 3);\
3869 compare_constants (const void *a, const void *b)
3871 const guint32 *a_values = a;
3872 const guint32 *b_values = b;
3873 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3877 compare_semantics (const void *a, const void *b)
3879 const guint32 *a_values = a;
3880 const guint32 *b_values = b;
3881 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3884 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3888 compare_custom_attrs (const void *a, const void *b)
3890 const guint32 *a_values = a;
3891 const guint32 *b_values = b;
3893 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3897 compare_field_marshal (const void *a, const void *b)
3899 const guint32 *a_values = a;
3900 const guint32 *b_values = b;
3902 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3906 compare_nested (const void *a, const void *b)
3908 const guint32 *a_values = a;
3909 const guint32 *b_values = b;
3911 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3915 compare_genericparam (const void *a, const void *b)
3917 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3918 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3920 if ((*b_entry)->owner == (*a_entry)->owner)
3922 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3923 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3925 return (*a_entry)->owner - (*b_entry)->owner;
3929 compare_declsecurity_attrs (const void *a, const void *b)
3931 const guint32 *a_values = a;
3932 const guint32 *b_values = b;
3934 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3938 compare_interface_impl (const void *a, const void *b)
3940 const guint32 *a_values = a;
3941 const guint32 *b_values = b;
3943 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3947 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3951 pad_heap (MonoDynamicStream *sh)
3953 if (sh->index & 3) {
3954 int sz = 4 - (sh->index & 3);
3955 memset (sh->data + sh->index, 0, sz);
3962 MonoDynamicStream *stream;
3966 * build_compressed_metadata() fills in the blob of data that represents the
3967 * raw metadata as it will be saved in the PE file. The five streams are output
3968 * and the metadata tables are comnpressed from the guint32 array representation,
3969 * to the compressed on-disk format.
3972 build_compressed_metadata (MonoDynamicImage *assembly)
3974 MonoDynamicTable *table;
3976 guint64 valid_mask = 0;
3977 guint64 sorted_mask;
3978 guint32 heapt_size = 0;
3979 guint32 meta_size = 256; /* allow for header and other stuff */
3980 guint32 table_offset;
3981 guint32 ntables = 0;
3987 struct StreamDesc stream_desc [5];
3989 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3990 for (i = 0; i < assembly->gen_params->len; i++){
3991 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3992 write_generic_param_entry (assembly, entry);
3995 stream_desc [0].name = "#~";
3996 stream_desc [0].stream = &assembly->tstream;
3997 stream_desc [1].name = "#Strings";
3998 stream_desc [1].stream = &assembly->sheap;
3999 stream_desc [2].name = "#US";
4000 stream_desc [2].stream = &assembly->us;
4001 stream_desc [3].name = "#Blob";
4002 stream_desc [3].stream = &assembly->blob;
4003 stream_desc [4].name = "#GUID";
4004 stream_desc [4].stream = &assembly->guid;
4006 /* tables that are sorted */
4007 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4008 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4009 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4010 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4011 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4012 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4013 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4015 /* Compute table sizes */
4016 /* the MonoImage has already been created in mono_image_basic_init() */
4017 meta = &assembly->image;
4019 /* sizes should be multiple of 4 */
4020 pad_heap (&assembly->blob);
4021 pad_heap (&assembly->guid);
4022 pad_heap (&assembly->sheap);
4023 pad_heap (&assembly->us);
4025 /* Setup the info used by compute_sizes () */
4026 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4027 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4028 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4030 meta_size += assembly->blob.index;
4031 meta_size += assembly->guid.index;
4032 meta_size += assembly->sheap.index;
4033 meta_size += assembly->us.index;
4035 for (i=0; i < MONO_TABLE_NUM; ++i)
4036 meta->tables [i].rows = assembly->tables [i].rows;
4038 for (i = 0; i < MONO_TABLE_NUM; i++){
4039 if (meta->tables [i].rows == 0)
4041 valid_mask |= (guint64)1 << i;
4043 meta->tables [i].row_size = mono_metadata_compute_size (
4044 meta, i, &meta->tables [i].size_bitfield);
4045 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4047 heapt_size += 24; /* #~ header size */
4048 heapt_size += ntables * 4;
4049 /* make multiple of 4 */
4052 meta_size += heapt_size;
4053 meta->raw_metadata = g_malloc0 (meta_size);
4054 p = (unsigned char*)meta->raw_metadata;
4055 /* the metadata signature */
4056 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4057 /* version numbers and 4 bytes reserved */
4058 int16val = (guint16*)p;
4059 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4060 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4062 /* version string */
4063 int32val = (guint32*)p;
4064 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4066 memcpy (p, meta->version, strlen (meta->version));
4067 p += GUINT32_FROM_LE (*int32val);
4068 align_pointer (meta->raw_metadata, p);
4069 int16val = (guint16*)p;
4070 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4071 *int16val = GUINT16_TO_LE (5); /* number of streams */
4075 * write the stream info.
4077 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4078 table_offset += 3; table_offset &= ~3;
4080 assembly->tstream.index = heapt_size;
4081 for (i = 0; i < 5; ++i) {
4082 int32val = (guint32*)p;
4083 stream_desc [i].stream->offset = table_offset;
4084 *int32val++ = GUINT32_TO_LE (table_offset);
4085 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4086 table_offset += GUINT32_FROM_LE (*int32val);
4087 table_offset += 3; table_offset &= ~3;
4089 strcpy ((char*)p, stream_desc [i].name);
4090 p += strlen (stream_desc [i].name) + 1;
4091 align_pointer (meta->raw_metadata, p);
4094 * now copy the data, the table stream header and contents goes first.
4096 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4097 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4098 int32val = (guint32*)p;
4099 *int32val = GUINT32_TO_LE (0); /* reserved */
4102 *p++ = 2; /* version */
4105 if (meta->idx_string_wide)
4107 if (meta->idx_guid_wide)
4109 if (meta->idx_blob_wide)
4112 *p++ = 1; /* reserved */
4113 int64val = (guint64*)p;
4114 *int64val++ = GUINT64_TO_LE (valid_mask);
4115 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4117 int32val = (guint32*)p;
4118 for (i = 0; i < MONO_TABLE_NUM; i++){
4119 if (meta->tables [i].rows == 0)
4121 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4123 p = (unsigned char*)int32val;
4125 /* sort the tables that still need sorting */
4126 table = &assembly->tables [MONO_TABLE_CONSTANT];
4128 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4129 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4131 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4132 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4134 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4135 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4137 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4138 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4140 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4141 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4142 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4144 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4145 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4147 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4149 /* compress the tables */
4150 for (i = 0; i < MONO_TABLE_NUM; i++){
4153 guint32 bitfield = meta->tables [i].size_bitfield;
4154 if (!meta->tables [i].rows)
4156 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4157 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4158 meta->tables [i].base = (char*)p;
4159 for (row = 1; row <= meta->tables [i].rows; ++row) {
4160 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4161 for (col = 0; col < assembly->tables [i].columns; ++col) {
4162 switch (mono_metadata_table_size (bitfield, col)) {
4164 *p++ = values [col];
4167 *p++ = values [col] & 0xff;
4168 *p++ = (values [col] >> 8) & 0xff;
4171 *p++ = values [col] & 0xff;
4172 *p++ = (values [col] >> 8) & 0xff;
4173 *p++ = (values [col] >> 16) & 0xff;
4174 *p++ = (values [col] >> 24) & 0xff;
4177 g_assert_not_reached ();
4181 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4184 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4185 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4186 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4187 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4188 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4190 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4194 * Some tables in metadata need to be sorted according to some criteria, but
4195 * when methods and fields are first created with reflection, they may be assigned a token
4196 * that doesn't correspond to the final token they will get assigned after the sorting.
4197 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4198 * with the reflection objects that represent them. Once all the tables are set up, the
4199 * reflection objects will contains the correct table index. fixup_method() will fixup the
4200 * tokens for the method with ILGenerator @ilgen.
4203 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4205 guint32 code_idx = GPOINTER_TO_UINT (value);
4206 MonoReflectionILTokenInfo *iltoken;
4207 MonoReflectionFieldBuilder *field;
4208 MonoReflectionCtorBuilder *ctor;
4209 MonoReflectionMethodBuilder *method;
4210 MonoReflectionTypeBuilder *tb;
4211 MonoReflectionArrayMethod *am;
4213 unsigned char *target;
4215 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4216 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4217 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4218 switch (target [3]) {
4219 case MONO_TABLE_FIELD:
4220 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4221 field = (MonoReflectionFieldBuilder *)iltoken->member;
4222 idx = field->table_idx;
4223 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4224 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4225 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4227 g_assert_not_reached ();
4230 case MONO_TABLE_METHOD:
4231 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4232 method = (MonoReflectionMethodBuilder *)iltoken->member;
4233 idx = method->table_idx;
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4235 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4236 idx = ctor->table_idx;
4237 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4238 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4239 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4240 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4242 g_assert_not_reached ();
4245 case MONO_TABLE_TYPEDEF:
4246 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4247 g_assert_not_reached ();
4248 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4249 idx = tb->table_idx;
4251 case MONO_TABLE_MEMBERREF:
4252 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4253 am = (MonoReflectionArrayMethod*)iltoken->member;
4254 idx = am->table_idx;
4255 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4256 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4257 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4258 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4259 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4260 g_assert (m->klass->generic_class || m->klass->generic_container);
4262 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4264 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4265 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4266 g_assert (is_field_on_inst (f));
4268 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4269 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4271 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4273 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4275 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4278 g_assert_not_reached ();
4281 case MONO_TABLE_METHODSPEC:
4282 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4283 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4284 g_assert (mono_method_signature (m)->generic_param_count);
4286 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4288 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4291 g_assert_not_reached ();
4295 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4297 target [0] = idx & 0xff;
4298 target [1] = (idx >> 8) & 0xff;
4299 target [2] = (idx >> 16) & 0xff;
4306 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4307 * value is not known when the table is emitted.
4310 fixup_cattrs (MonoDynamicImage *assembly)
4312 MonoDynamicTable *table;
4314 guint32 type, i, idx, token;
4317 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4319 for (i = 0; i < table->rows; ++i) {
4320 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4322 type = values [MONO_CUSTOM_ATTR_TYPE];
4323 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4324 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4325 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4326 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4329 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")|| !strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4330 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4331 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4332 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4339 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4341 MonoDynamicTable *table;
4344 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4346 alloc_table (table, table->rows);
4347 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4348 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4349 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4350 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4351 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4356 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4358 MonoDynamicTable *table;
4362 char *b = blob_size;
4364 guint32 idx, offset;
4366 if (rsrc->filename) {
4367 name = mono_string_to_utf8 (rsrc->filename);
4368 sname = g_path_get_basename (name);
4370 table = &assembly->tables [MONO_TABLE_FILE];
4372 alloc_table (table, table->rows);
4373 values = table->values + table->next_idx * MONO_FILE_SIZE;
4374 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4375 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4378 mono_sha1_get_digest_from_file (name, hash);
4379 mono_metadata_encode_value (20, b, &b);
4380 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4381 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4383 idx = table->next_idx++;
4385 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4391 data = mono_array_addr (rsrc->data, char, 0);
4392 len = mono_array_length (rsrc->data);
4398 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4399 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4400 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4401 mono_image_add_stream_data (&assembly->resources, data, len);
4405 * The entry should be emitted into the MANIFESTRESOURCE table of
4406 * the main module, but that needs to reference the FILE table
4407 * which isn't emitted yet.
4414 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4418 set_version_from_string (MonoString *version, guint32 *values)
4420 gchar *ver, *p, *str;
4423 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4424 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4425 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4426 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4429 ver = str = mono_string_to_utf8 (version);
4430 for (i = 0; i < 4; ++i) {
4431 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4437 /* handle Revision and Build */
4447 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4451 char *b = blob_size;
4456 len = mono_array_length (pkey);
4457 mono_metadata_encode_value (len, b, &b);
4458 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4459 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4461 assembly->public_key = g_malloc (len);
4462 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4463 assembly->public_key_len = len;
4465 /* Special case: check for ECMA key (16 bytes) */
4466 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4467 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4468 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4469 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4470 /* minimum key size (in 2.0) is 384 bits */
4471 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4473 /* FIXME - verifier */
4474 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4475 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4477 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4483 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4485 MonoDynamicTable *table;
4486 MonoDynamicImage *assembly;
4487 MonoReflectionAssemblyBuilder *assemblyb;
4491 guint32 module_index;
4493 assemblyb = moduleb->assemblyb;
4494 assembly = moduleb->dynamic_image;
4495 domain = mono_object_domain (assemblyb);
4497 /* Emit ASSEMBLY table */
4498 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4499 alloc_table (table, 1);
4500 values = table->values + MONO_ASSEMBLY_SIZE;
4501 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4502 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4503 if (assemblyb->culture) {
4504 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4506 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4508 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4509 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4510 set_version_from_string (assemblyb->version, values);
4512 /* Emit FILE + EXPORTED_TYPE table */
4514 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4516 MonoReflectionModuleBuilder *file_module =
4517 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518 if (file_module != moduleb) {
4519 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4521 if (file_module->types) {
4522 for (j = 0; j < file_module->num_types; ++j) {
4523 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4524 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4529 if (assemblyb->loaded_modules) {
4530 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4531 MonoReflectionModule *file_module =
4532 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4533 mono_image_fill_file_table (domain, file_module, assembly);
4535 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4538 if (assemblyb->type_forwarders)
4539 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4541 /* Emit MANIFESTRESOURCE table */
4543 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4545 MonoReflectionModuleBuilder *file_module =
4546 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4547 /* The table for the main module is emitted later */
4548 if (file_module != moduleb) {
4550 if (file_module->resources) {
4551 int len = mono_array_length (file_module->resources);
4552 for (j = 0; j < len; ++j) {
4553 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4554 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4561 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4564 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4565 * for the modulebuilder @moduleb.
4566 * At the end of the process, method and field tokens are fixed up and the
4567 * on-disk compressed metadata representation is created.
4570 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4572 MonoDynamicTable *table;
4573 MonoDynamicImage *assembly;
4574 MonoReflectionAssemblyBuilder *assemblyb;
4580 assemblyb = moduleb->assemblyb;
4581 assembly = moduleb->dynamic_image;
4582 domain = mono_object_domain (assemblyb);
4584 if (assembly->text_rva)
4587 assembly->text_rva = START_TEXT_RVA;
4589 if (moduleb->is_main) {
4590 mono_image_emit_manifest (moduleb);
4593 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4594 table->rows = 1; /* .<Module> */
4596 alloc_table (table, table->rows);
4598 * Set the first entry.
4600 values = table->values + table->columns;
4601 values [MONO_TYPEDEF_FLAGS] = 0;
4602 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4603 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4604 values [MONO_TYPEDEF_EXTENDS] = 0;
4605 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4606 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4609 * handle global methods
4610 * FIXME: test what to do when global methods are defined in multiple modules.
4612 if (moduleb->global_methods) {
4613 table = &assembly->tables [MONO_TABLE_METHOD];
4614 table->rows += mono_array_length (moduleb->global_methods);
4615 alloc_table (table, table->rows);
4616 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4617 mono_image_get_method_info (
4618 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4620 if (moduleb->global_fields) {
4621 table = &assembly->tables [MONO_TABLE_FIELD];
4622 table->rows += mono_array_length (moduleb->global_fields);
4623 alloc_table (table, table->rows);
4624 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4625 mono_image_get_field_info (
4626 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4629 table = &assembly->tables [MONO_TABLE_MODULE];
4630 alloc_table (table, 1);
4631 mono_image_fill_module_table (domain, moduleb, assembly);
4633 /* Collect all types into a list sorted by their table_idx */
4634 mono_ptr_array_init (types, moduleb->num_types);
4637 for (i = 0; i < moduleb->num_types; ++i) {
4638 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4639 collect_types (&types, type);
4642 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4643 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4644 table->rows += mono_ptr_array_size (types);
4645 alloc_table (table, table->rows);
4648 * Emit type names + namespaces at one place inside the string heap,
4649 * so load_class_names () needs to touch fewer pages.
4651 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4652 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4653 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4655 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4656 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4657 string_heap_insert_mstring (&assembly->sheap, tb->name);
4660 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4661 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4662 mono_image_get_type_info (domain, type, assembly);
4666 * table->rows is already set above and in mono_image_fill_module_table.
4668 /* add all the custom attributes at the end, once all the indexes are stable */
4669 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4671 /* CAS assembly permissions */
4672 if (assemblyb->permissions_minimum)
4673 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4674 if (assemblyb->permissions_optional)
4675 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4676 if (assemblyb->permissions_refused)
4677 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4679 module_add_cattrs (assembly, moduleb);
4682 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4684 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4685 * the final tokens and don't need another fixup pass. */
4687 if (moduleb->global_methods) {
4688 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4689 MonoReflectionMethodBuilder *mb = mono_array_get (
4690 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4691 mono_image_add_methodimpl (assembly, mb);
4695 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4696 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4697 if (type->methods) {
4698 for (j = 0; j < type->num_methods; ++j) {
4699 MonoReflectionMethodBuilder *mb = mono_array_get (
4700 type->methods, MonoReflectionMethodBuilder*, j);
4702 mono_image_add_methodimpl (assembly, mb);
4707 mono_ptr_array_destroy (types);
4709 fixup_cattrs (assembly);
4712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4715 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4717 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4724 guint32 import_lookup_table;
4728 guint32 import_address_table_rva;
4736 #ifndef DISABLE_REFLECTION_EMIT
4739 * mono_image_insert_string:
4740 * @module: module builder object
4743 * Insert @str into the user string stream of @module.
4746 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4748 MonoDynamicImage *assembly;
4753 MONO_ARCH_SAVE_REGS;
4755 if (!module->dynamic_image)
4756 mono_image_module_basic_init (module);
4758 assembly = module->dynamic_image;
4760 if (assembly->save) {
4761 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4762 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4763 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4765 char *swapped = g_malloc (2 * mono_string_length (str));
4766 const char *p = (const char*)mono_string_chars (str);
4768 swap_with_size (swapped, p, 2, mono_string_length (str));
4769 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4773 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4775 mono_image_add_stream_data (&assembly->us, "", 1);
4777 idx = assembly->us.index ++;
4780 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4782 return MONO_TOKEN_STRING | idx;
4786 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4790 MonoMethodSignature *sig;
4792 klass = obj->vtable->klass;
4793 if (strcmp (klass->name, "MonoMethod") == 0) {
4794 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4795 MonoMethodSignature *old;
4796 guint32 sig_token, parent;
4799 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4801 nargs = mono_array_length (opt_param_types);
4802 old = mono_method_signature (method);
4803 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4805 sig->hasthis = old->hasthis;
4806 sig->explicit_this = old->explicit_this;
4807 sig->call_convention = old->call_convention;
4808 sig->generic_param_count = old->generic_param_count;
4809 sig->param_count = old->param_count + nargs;
4810 sig->sentinelpos = old->param_count;
4811 sig->ret = old->ret;
4813 for (i = 0; i < old->param_count; i++)
4814 sig->params [i] = old->params [i];
4816 for (i = 0; i < nargs; i++) {
4817 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4818 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4821 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4822 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4823 parent >>= MONO_TYPEDEFORREF_BITS;
4825 parent <<= MONO_MEMBERREF_PARENT_BITS;
4826 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4828 sig_token = method_encode_signature (assembly, sig);
4829 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4830 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4831 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4832 ReflectionMethodBuilder rmb;
4833 guint32 parent, sig_token;
4834 int nopt_args, nparams, ngparams, i;
4837 reflection_methodbuilder_from_method_builder (&rmb, mb);
4838 rmb.opt_types = opt_param_types;
4839 nopt_args = mono_array_length (opt_param_types);
4841 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4842 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4843 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4845 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4846 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4847 sig->call_convention = rmb.call_conv;
4848 sig->generic_param_count = ngparams;
4849 sig->param_count = nparams + nopt_args;
4850 sig->sentinelpos = nparams;
4851 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4853 for (i = 0; i < nparams; i++) {
4854 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4855 sig->params [i] = mono_reflection_type_get_handle (rt);
4858 for (i = 0; i < nopt_args; i++) {
4859 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4860 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4863 sig_token = method_builder_encode_signature (assembly, &rmb);
4865 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4866 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4868 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4869 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4871 name = mono_string_to_utf8 (rmb.name);
4872 token = mono_image_get_varargs_method_token (
4873 assembly, parent, name, sig_token);
4876 g_error ("requested method token for %s\n", klass->name);
4879 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4880 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4885 * mono_image_create_token:
4886 * @assembly: a dynamic assembly
4888 * @register_token: Whenever to register the token in the assembly->tokens hash.
4890 * Get a token to insert in the IL code stream for the given MemberInfo.
4891 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4892 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4896 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4897 gboolean create_open_instance, gboolean register_token)
4902 klass = obj->vtable->klass;
4904 /* Check for user defined reflection objects */
4905 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4906 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4907 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4909 if (strcmp (klass->name, "MethodBuilder") == 0) {
4910 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4911 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4913 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4914 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4916 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4917 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4918 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4919 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4920 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4922 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4923 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4925 token = mono_image_get_ctorbuilder_token (assembly, mb);
4926 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4927 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4928 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4929 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4930 if (tb->generic_params) {
4931 token = mono_image_get_generic_field_token (assembly, fb);
4933 if (tb->module->dynamic_image == assembly) {
4934 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4936 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4939 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4940 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4941 if (create_open_instance && tb->generic_params) {
4943 init_type_builder_generics (obj);
4944 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4945 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4946 token = mono_metadata_token_from_dor (token);
4947 } else if (tb->module->dynamic_image == assembly) {
4948 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4951 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4952 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4954 } else if (strcmp (klass->name, "MonoType") == 0) {
4955 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4956 MonoClass *mc = mono_class_from_mono_type (type);
4957 token = mono_metadata_token_from_dor (
4958 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4959 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4960 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4961 token = mono_metadata_token_from_dor (
4962 mono_image_typedef_or_ref (assembly, type));
4963 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4964 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4965 token = mono_metadata_token_from_dor (
4966 mono_image_typedef_or_ref (assembly, type));
4967 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4968 strcmp (klass->name, "MonoMethod") == 0 ||
4969 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4970 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4971 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4972 if (m->method->is_inflated) {
4973 if (create_open_instance)
4974 token = mono_image_get_methodspec_token (assembly, m->method);
4976 token = mono_image_get_inflated_method_token (assembly, m->method);
4977 } else if ((m->method->klass->image == &assembly->image) &&
4978 !m->method->klass->generic_class) {
4979 static guint32 method_table_idx = 0xffffff;
4980 if (m->method->klass->wastypebuilder) {
4981 /* we use the same token as the one that was assigned
4982 * to the Methodbuilder.
4983 * FIXME: do the equivalent for Fields.
4985 token = m->method->token;
4988 * Each token should have a unique index, but the indexes are
4989 * assigned by managed code, so we don't know about them. An
4990 * easy solution is to count backwards...
4992 method_table_idx --;
4993 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4996 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4998 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4999 } else if (strcmp (klass->name, "MonoField") == 0) {
5000 MonoReflectionField *f = (MonoReflectionField *)obj;
5001 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5002 static guint32 field_table_idx = 0xffffff;
5004 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5006 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5008 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5009 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5010 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5011 token = mono_image_get_array_token (assembly, m);
5012 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5013 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5014 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5015 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5016 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5017 token = mono_metadata_token_from_dor (
5018 mono_image_typedef_or_ref (assembly, type));
5019 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5020 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5021 token = mono_image_get_field_on_inst_token (assembly, f);
5022 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5023 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5024 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5025 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5026 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5027 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5028 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5029 MonoReflectionType *type = (MonoReflectionType *)obj;
5030 token = mono_metadata_token_from_dor (
5031 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5033 g_error ("requested token for %s\n", klass->name);
5037 mono_image_register_token (assembly, token, obj);
5043 * mono_image_register_token:
5045 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5046 * the Module.ResolveXXXToken () methods to work.
5049 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5051 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5053 /* There could be multiple MethodInfo objects with the same token */
5054 //g_assert (prev == obj);
5056 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5060 static MonoDynamicImage*
5061 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5063 static const guchar entrycode [16] = {0xff, 0x25, 0};
5064 MonoDynamicImage *image;
5067 const char *version;
5069 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5070 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5072 version = mono_get_runtime_info ()->runtime_version;
5075 /* The MonoGHashTable's need GC tracking */
5076 image = GC_MALLOC (sizeof (MonoDynamicImage));
5078 image = g_new0 (MonoDynamicImage, 1);
5081 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5083 /*g_print ("created image %p\n", image);*/
5084 /* keep in sync with image.c */
5085 image->image.name = assembly_name;
5086 image->image.assembly_name = image->image.name; /* they may be different */
5087 image->image.module_name = module_name;
5088 image->image.version = g_strdup (version);
5089 image->image.md_version_major = 1;
5090 image->image.md_version_minor = 1;
5091 image->image.dynamic = TRUE;
5093 image->image.references = g_new0 (MonoAssembly*, 1);
5094 image->image.references [0] = NULL;
5096 mono_image_init (&image->image);
5098 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5099 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5100 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5101 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5102 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5103 image->handleref = g_hash_table_new (NULL, NULL);
5104 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5105 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5107 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5108 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5110 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5111 image->gen_params = g_ptr_array_new ();
5113 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5114 string_heap_init (&image->sheap);
5115 mono_image_add_stream_data (&image->us, "", 1);
5116 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5117 /* import tables... */
5118 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5119 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5120 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5121 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5122 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5123 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5124 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5125 stream_data_align (&image->code);
5127 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5129 for (i=0; i < MONO_TABLE_NUM; ++i) {
5130 image->tables [i].next_idx = 1;
5131 image->tables [i].columns = table_sizes [i];
5134 image->image.assembly = (MonoAssembly*)assembly;
5135 image->run = assembly->run;
5136 image->save = assembly->save;
5137 image->pe_kind = 0x1; /* ILOnly */
5138 image->machine = 0x14c; /* I386 */
5140 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5147 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5153 release_hashtable (MonoGHashTable **hash)
5156 mono_g_hash_table_destroy (*hash);
5162 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5164 release_hashtable (&image->token_fixups);
5165 release_hashtable (&image->handleref_managed);
5166 release_hashtable (&image->tokens);
5167 release_hashtable (&image->generic_def_objects);
5168 release_hashtable (&image->methodspec);
5172 mono_dynamic_image_free (MonoDynamicImage *image)
5174 MonoDynamicImage *di = image;
5179 mono_g_hash_table_destroy (di->methodspec);
5181 g_hash_table_destroy (di->typespec);
5183 g_hash_table_destroy (di->typeref);
5185 g_hash_table_destroy (di->handleref);
5186 if (di->handleref_managed)
5187 mono_g_hash_table_destroy (di->handleref_managed);
5189 mono_g_hash_table_destroy (di->tokens);
5190 if (di->generic_def_objects)
5191 mono_g_hash_table_destroy (di->generic_def_objects);
5192 if (di->blob_cache) {
5193 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5194 g_hash_table_destroy (di->blob_cache);
5196 if (di->standalonesig_cache)
5197 g_hash_table_destroy (di->standalonesig_cache);
5198 for (list = di->array_methods; list; list = list->next) {
5199 ArrayMethod *am = (ArrayMethod *)list->data;
5204 g_list_free (di->array_methods);
5205 if (di->gen_params) {
5206 for (i = 0; i < di->gen_params->len; i++) {
5207 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5208 mono_gc_deregister_root ((char*) &entry->gparam);
5211 g_ptr_array_free (di->gen_params, TRUE);
5213 if (di->token_fixups)
5214 mono_g_hash_table_destroy (di->token_fixups);
5215 if (di->method_to_table_idx)
5216 g_hash_table_destroy (di->method_to_table_idx);
5217 if (di->field_to_table_idx)
5218 g_hash_table_destroy (di->field_to_table_idx);
5219 if (di->method_aux_hash)
5220 g_hash_table_destroy (di->method_aux_hash);
5221 if (di->vararg_aux_hash)
5222 g_hash_table_destroy (di->vararg_aux_hash);
5223 g_free (di->strong_name);
5224 g_free (di->win32_res);
5226 g_free (di->public_key);
5228 /*g_print ("string heap destroy for image %p\n", di);*/
5229 mono_dynamic_stream_reset (&di->sheap);
5230 mono_dynamic_stream_reset (&di->code);
5231 mono_dynamic_stream_reset (&di->resources);
5232 mono_dynamic_stream_reset (&di->us);
5233 mono_dynamic_stream_reset (&di->blob);
5234 mono_dynamic_stream_reset (&di->tstream);
5235 mono_dynamic_stream_reset (&di->guid);
5236 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5237 g_free (di->tables [i].values);
5241 #ifndef DISABLE_REFLECTION_EMIT
5244 * mono_image_basic_init:
5245 * @assembly: an assembly builder object
5247 * Create the MonoImage that represents the assembly builder and setup some
5248 * of the helper hash table and the basic metadata streams.
5251 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5253 MonoDynamicAssembly *assembly;
5254 MonoDynamicImage *image;
5255 MonoDomain *domain = mono_object_domain (assemblyb);
5257 MONO_ARCH_SAVE_REGS;
5259 if (assemblyb->dynamic_assembly)
5263 /* assembly->assembly.image might be GC allocated */
5264 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5266 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5269 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5271 assembly->assembly.ref_count = 1;
5272 assembly->assembly.dynamic = TRUE;
5273 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5274 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5275 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5276 if (assemblyb->culture)
5277 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5279 assembly->assembly.aname.culture = g_strdup ("");
5281 if (assemblyb->version) {
5282 char *vstr = mono_string_to_utf8 (assemblyb->version);
5283 char **version = g_strsplit (vstr, ".", 4);
5284 char **parts = version;
5285 assembly->assembly.aname.major = atoi (*parts++);
5286 assembly->assembly.aname.minor = atoi (*parts++);
5287 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5288 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5290 g_strfreev (version);
5293 assembly->assembly.aname.major = 0;
5294 assembly->assembly.aname.minor = 0;
5295 assembly->assembly.aname.build = 0;
5296 assembly->assembly.aname.revision = 0;
5299 assembly->run = assemblyb->access != 2;
5300 assembly->save = assemblyb->access != 1;
5301 assembly->domain = domain;
5303 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5304 image->initial_image = TRUE;
5305 assembly->assembly.aname.name = image->image.name;
5306 assembly->assembly.image = &image->image;
5307 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5308 /* -1 to correct for the trailing NULL byte */
5309 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5310 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5312 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5315 mono_domain_assemblies_lock (domain);
5316 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5317 mono_domain_assemblies_unlock (domain);
5319 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5321 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5323 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5326 #endif /* !DISABLE_REFLECTION_EMIT */
5328 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5331 calc_section_size (MonoDynamicImage *assembly)
5335 /* alignment constraints */
5336 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5337 g_assert ((assembly->code.index % 4) == 0);
5338 assembly->meta_size += 3;
5339 assembly->meta_size &= ~3;
5340 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5341 g_assert ((assembly->resources.index % 4) == 0);
5343 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5344 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5347 if (assembly->win32_res) {
5348 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5350 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5351 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5355 assembly->sections [MONO_SECTION_RELOC].size = 12;
5356 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5366 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5370 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5372 ResTreeNode *t1 = (ResTreeNode*)a;
5373 ResTreeNode *t2 = (ResTreeNode*)b;
5375 return t1->id - t2->id;
5379 * resource_tree_create:
5381 * Organize the resources into a resource tree.
5383 static ResTreeNode *
5384 resource_tree_create (MonoArray *win32_resources)
5386 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5390 tree = g_new0 (ResTreeNode, 1);
5392 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5393 MonoReflectionWin32Resource *win32_res =
5394 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5398 /* FIXME: BUG: this stores managed references in unmanaged memory */
5399 lang_node = g_new0 (ResTreeNode, 1);
5400 lang_node->id = win32_res->lang_id;
5401 lang_node->win32_res = win32_res;
5403 /* Create type node if neccesary */
5405 for (l = tree->children; l; l = l->next)
5406 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5407 type_node = (ResTreeNode*)l->data;
5412 type_node = g_new0 (ResTreeNode, 1);
5413 type_node->id = win32_res->res_type;
5416 * The resource types have to be sorted otherwise
5417 * Windows Explorer can't display the version information.
5419 tree->children = g_slist_insert_sorted (tree->children,
5420 type_node, resource_tree_compare_by_id);
5423 /* Create res node if neccesary */
5425 for (l = type_node->children; l; l = l->next)
5426 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5427 res_node = (ResTreeNode*)l->data;
5432 res_node = g_new0 (ResTreeNode, 1);
5433 res_node->id = win32_res->res_id;
5434 type_node->children = g_slist_append (type_node->children, res_node);
5437 res_node->children = g_slist_append (res_node->children, lang_node);
5444 * resource_tree_encode:
5446 * Encode the resource tree into the format used in the PE file.
5449 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5452 MonoPEResourceDir dir;
5453 MonoPEResourceDirEntry dir_entry;
5454 MonoPEResourceDataEntry data_entry;
5456 guint32 res_id_entries;
5459 * For the format of the resource directory, see the article
5460 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5464 memset (&dir, 0, sizeof (dir));
5465 memset (&dir_entry, 0, sizeof (dir_entry));
5466 memset (&data_entry, 0, sizeof (data_entry));
5468 g_assert (sizeof (dir) == 16);
5469 g_assert (sizeof (dir_entry) == 8);
5470 g_assert (sizeof (data_entry) == 16);
5472 node->offset = p - begin;
5474 /* IMAGE_RESOURCE_DIRECTORY */
5475 res_id_entries = g_slist_length (node->children);
5476 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5478 memcpy (p, &dir, sizeof (dir));
5481 /* Reserve space for entries */
5483 p += sizeof (dir_entry) * res_id_entries;
5485 /* Write children */
5486 for (l = node->children; l; l = l->next) {
5487 ResTreeNode *child = (ResTreeNode*)l->data;
5489 if (child->win32_res) {
5492 child->offset = p - begin;
5494 /* IMAGE_RESOURCE_DATA_ENTRY */
5495 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5496 size = mono_array_length (child->win32_res->res_data);
5497 data_entry.rde_size = GUINT32_TO_LE (size);
5499 memcpy (p, &data_entry, sizeof (data_entry));
5500 p += sizeof (data_entry);
5502 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5505 resource_tree_encode (child, begin, p, &p);
5509 /* IMAGE_RESOURCE_ENTRY */
5510 for (l = node->children; l; l = l->next) {
5511 ResTreeNode *child = (ResTreeNode*)l->data;
5513 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5514 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5516 memcpy (entries, &dir_entry, sizeof (dir_entry));
5517 entries += sizeof (dir_entry);
5524 resource_tree_free (ResTreeNode * node)
5527 for (list = node->children; list; list = list->next)
5528 resource_tree_free ((ResTreeNode*)list->data);
5529 g_slist_free(node->children);
5534 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5539 MonoReflectionWin32Resource *win32_res;
5542 if (!assemblyb->win32_resources)
5546 * Resources are stored in a three level tree inside the PE file.
5547 * - level one contains a node for each type of resource
5548 * - level two contains a node for each resource
5549 * - level three contains a node for each instance of a resource for a
5550 * specific language.
5553 tree = resource_tree_create (assemblyb->win32_resources);
5555 /* Estimate the size of the encoded tree */
5557 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5558 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5559 size += mono_array_length (win32_res->res_data);
5561 /* Directory structure */
5562 size += mono_array_length (assemblyb->win32_resources) * 256;
5563 p = buf = g_malloc (size);
5565 resource_tree_encode (tree, p, p, &p);
5567 g_assert (p - buf <= size);
5569 assembly->win32_res = g_malloc (p - buf);
5570 assembly->win32_res_size = p - buf;
5571 memcpy (assembly->win32_res, buf, p - buf);
5574 resource_tree_free (tree);
5578 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5580 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5583 p += sizeof (MonoPEResourceDir);
5584 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5585 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5586 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5587 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5588 fixup_resource_directory (res_section, child, rva);
5590 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5591 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5594 p += sizeof (MonoPEResourceDirEntry);
5599 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5602 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5603 g_error ("WriteFile returned %d\n", GetLastError ());
5607 * mono_image_create_pefile:
5608 * @mb: a module builder object
5610 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5611 * assembly->pefile where it can be easily retrieved later in chunks.
5614 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5616 MonoMSDOSHeader *msdos;
5617 MonoDotNetHeader *header;
5618 MonoSectionTable *section;
5619 MonoCLIHeader *cli_header;
5620 guint32 size, image_size, virtual_base, text_offset;
5621 guint32 header_start, section_start, file_offset, virtual_offset;
5622 MonoDynamicImage *assembly;
5623 MonoReflectionAssemblyBuilder *assemblyb;
5624 MonoDynamicStream pefile_stream = {0};
5625 MonoDynamicStream *pefile = &pefile_stream;
5627 guint32 *rva, value;
5629 static const unsigned char msheader[] = {
5630 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5631 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5634 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5635 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5636 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5637 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5640 assemblyb = mb->assemblyb;
5642 mono_image_basic_init (assemblyb);
5643 assembly = mb->dynamic_image;
5645 assembly->pe_kind = assemblyb->pe_kind;
5646 assembly->machine = assemblyb->machine;
5647 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5648 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5650 mono_image_build_metadata (mb);
5652 if (mb->is_main && assemblyb->resources) {
5653 int len = mono_array_length (assemblyb->resources);
5654 for (i = 0; i < len; ++i)
5655 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5658 if (mb->resources) {
5659 int len = mono_array_length (mb->resources);
5660 for (i = 0; i < len; ++i)
5661 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5664 build_compressed_metadata (assembly);
5667 assembly_add_win32_resources (assembly, assemblyb);
5669 nsections = calc_section_size (assembly);
5671 /* The DOS header and stub */
5672 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5673 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5675 /* the dotnet header */
5676 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5678 /* the section tables */
5679 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5681 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5682 virtual_offset = VIRT_ALIGN;
5685 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5686 if (!assembly->sections [i].size)
5689 file_offset += FILE_ALIGN - 1;
5690 file_offset &= ~(FILE_ALIGN - 1);
5691 virtual_offset += VIRT_ALIGN - 1;
5692 virtual_offset &= ~(VIRT_ALIGN - 1);
5694 assembly->sections [i].offset = file_offset;
5695 assembly->sections [i].rva = virtual_offset;
5697 file_offset += assembly->sections [i].size;
5698 virtual_offset += assembly->sections [i].size;
5699 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5702 file_offset += FILE_ALIGN - 1;
5703 file_offset &= ~(FILE_ALIGN - 1);
5705 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5707 /* back-patch info */
5708 msdos = (MonoMSDOSHeader*)pefile->data;
5709 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5711 header = (MonoDotNetHeader*)(pefile->data + header_start);
5712 header->pesig [0] = 'P';
5713 header->pesig [1] = 'E';
5715 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5716 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5717 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5718 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5719 if (assemblyb->pekind == 1) {
5721 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5724 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5727 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5729 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5730 header->pe.pe_major = 6;
5731 header->pe.pe_minor = 0;
5732 size = assembly->sections [MONO_SECTION_TEXT].size;
5733 size += FILE_ALIGN - 1;
5734 size &= ~(FILE_ALIGN - 1);
5735 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5736 size = assembly->sections [MONO_SECTION_RSRC].size;
5737 size += FILE_ALIGN - 1;
5738 size &= ~(FILE_ALIGN - 1);
5739 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5740 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5741 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5742 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5743 /* pe_rva_entry_point always at the beginning of the text section */
5744 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5746 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5747 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5748 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5749 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5750 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5751 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5752 size = section_start;
5753 size += FILE_ALIGN - 1;
5754 size &= ~(FILE_ALIGN - 1);
5755 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5757 size += VIRT_ALIGN - 1;
5758 size &= ~(VIRT_ALIGN - 1);
5759 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5762 // Translate the PEFileKind value to the value expected by the Windows loader
5768 // PEFileKinds.Dll == 1
5769 // PEFileKinds.ConsoleApplication == 2
5770 // PEFileKinds.WindowApplication == 3
5773 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5774 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5776 if (assemblyb->pekind == 3)
5781 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5783 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5784 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5785 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5786 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5787 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5788 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5790 /* fill data directory entries */
5792 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5793 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5795 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5796 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5798 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5799 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5800 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5801 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5802 /* patch entrypoint name */
5803 if (assemblyb->pekind == 1)
5804 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5806 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5807 /* patch imported function RVA name */
5808 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5809 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5811 /* the import table */
5812 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5813 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5814 /* patch imported dll RVA name and other entries in the dir */
5815 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5816 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5817 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5818 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5819 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5820 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5822 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5823 value = (assembly->text_rva + assembly->imp_names_offset);
5824 *p++ = (value) & 0xff;
5825 *p++ = (value >> 8) & (0xff);
5826 *p++ = (value >> 16) & (0xff);
5827 *p++ = (value >> 24) & (0xff);
5829 /* the CLI header info */
5830 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5831 cli_header->ch_size = GUINT32_FROM_LE (72);
5832 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5833 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5834 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5835 if (assemblyb->entry_point) {
5836 guint32 table_idx = 0;
5837 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5838 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5839 table_idx = methodb->table_idx;
5841 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5843 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5845 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5847 /* The embedded managed resources */
5848 text_offset = assembly->text_rva + assembly->code.index;
5849 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5850 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5851 text_offset += assembly->resources.index;
5852 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5853 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5854 text_offset += assembly->meta_size;
5855 if (assembly->strong_name_size) {
5856 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5857 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5858 text_offset += assembly->strong_name_size;
5861 /* write the section tables and section content */
5862 section = (MonoSectionTable*)(pefile->data + section_start);
5863 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5864 static const char section_names [][7] = {
5865 ".text", ".rsrc", ".reloc"
5867 if (!assembly->sections [i].size)
5869 strcpy (section->st_name, section_names [i]);
5870 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5871 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5872 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5873 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5874 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5875 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5876 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5880 checked_write_file (file, pefile->data, pefile->index);
5882 mono_dynamic_stream_reset (pefile);
5884 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5885 if (!assembly->sections [i].size)
5888 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5889 g_error ("SetFilePointer returned %d\n", GetLastError ());
5892 case MONO_SECTION_TEXT:
5893 /* patch entry point */
5894 p = (guchar*)(assembly->code.data + 2);
5895 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5896 *p++ = (value) & 0xff;
5897 *p++ = (value >> 8) & 0xff;
5898 *p++ = (value >> 16) & 0xff;
5899 *p++ = (value >> 24) & 0xff;
5901 checked_write_file (file, assembly->code.data, assembly->code.index);
5902 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5903 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5904 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5907 g_free (assembly->image.raw_metadata);
5909 case MONO_SECTION_RELOC: {
5913 guint16 type_and_offset;
5917 g_assert (sizeof (reloc) == 12);
5919 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5920 reloc.block_size = GUINT32_FROM_LE (12);
5923 * the entrypoint is always at the start of the text section
5924 * 3 is IMAGE_REL_BASED_HIGHLOW
5925 * 2 is patch_size_rva - text_rva
5927 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5930 checked_write_file (file, &reloc, sizeof (reloc));
5934 case MONO_SECTION_RSRC:
5935 if (assembly->win32_res) {
5937 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5938 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5939 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5943 g_assert_not_reached ();
5947 /* check that the file is properly padded */
5948 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5949 g_error ("SetFilePointer returned %d\n", GetLastError ());
5950 if (! SetEndOfFile (file))
5951 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5953 mono_dynamic_stream_reset (&assembly->code);
5954 mono_dynamic_stream_reset (&assembly->us);
5955 mono_dynamic_stream_reset (&assembly->blob);
5956 mono_dynamic_stream_reset (&assembly->guid);
5957 mono_dynamic_stream_reset (&assembly->sheap);
5959 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5960 g_hash_table_destroy (assembly->blob_cache);
5961 assembly->blob_cache = NULL;
5964 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5967 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5969 g_assert_not_reached ();
5972 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5974 #ifndef DISABLE_REFLECTION_EMIT
5976 MonoReflectionModule *
5977 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5981 MonoImageOpenStatus status;
5982 MonoDynamicAssembly *assembly;
5983 guint32 module_count;
5984 MonoImage **new_modules;
5985 gboolean *new_modules_loaded;
5987 name = mono_string_to_utf8 (fileName);
5989 image = mono_image_open (name, &status);
5992 if (status == MONO_IMAGE_ERROR_ERRNO)
5993 exc = mono_get_exception_file_not_found (fileName);
5995 exc = mono_get_exception_bad_image_format (name);
5997 mono_raise_exception (exc);
6002 assembly = ab->dynamic_assembly;
6003 image->assembly = (MonoAssembly*)assembly;
6005 module_count = image->assembly->image->module_count;
6006 new_modules = g_new0 (MonoImage *, module_count + 1);
6007 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6009 if (image->assembly->image->modules)
6010 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6011 if (image->assembly->image->modules_loaded)
6012 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6013 new_modules [module_count] = image;
6014 new_modules_loaded [module_count] = TRUE;
6015 mono_image_addref (image);
6017 g_free (image->assembly->image->modules);
6018 image->assembly->image->modules = new_modules;
6019 image->assembly->image->modules_loaded = new_modules_loaded;
6020 image->assembly->image->module_count ++;
6022 mono_assembly_load_references (image, &status);
6024 mono_image_close (image);
6025 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6028 return mono_module_get_object (mono_domain_get (), image);
6031 #endif /* DISABLE_REFLECTION_EMIT */
6034 * We need to return always the same object for MethodInfo, FieldInfo etc..
6035 * but we need to consider the reflected type.
6036 * type uses a different hash, since it uses custom hash/equal functions.
6041 MonoClass *refclass;
6045 reflected_equal (gconstpointer a, gconstpointer b) {
6046 const ReflectedEntry *ea = a;
6047 const ReflectedEntry *eb = b;
6049 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6053 reflected_hash (gconstpointer a) {
6054 const ReflectedEntry *ea = a;
6055 return mono_aligned_addr_hash (ea->item);
6058 #define CHECK_OBJECT(t,p,k) \
6064 mono_domain_lock (domain); \
6065 if (!domain->refobject_hash) \
6066 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6067 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6068 mono_domain_unlock (domain); \
6071 mono_domain_unlock (domain); \
6074 #ifdef HAVE_BOEHM_GC
6075 /* ReflectedEntry doesn't need to be GC tracked */
6076 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6077 #define FREE_REFENTRY(entry) g_free ((entry))
6078 #define REFENTRY_REQUIRES_CLEANUP
6080 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6082 #define FREE_REFENTRY(entry)
6085 #define CACHE_OBJECT(t,p,o,k) \
6088 ReflectedEntry pe; \
6090 pe.refclass = (k); \
6091 mono_domain_lock (domain); \
6092 if (!domain->refobject_hash) \
6093 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6094 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6096 ReflectedEntry *e = ALLOC_REFENTRY; \
6098 e->refclass = (k); \
6099 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6102 mono_domain_unlock (domain); \
6107 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6109 mono_domain_lock (domain);
6110 if (domain->refobject_hash) {
6112 gpointer orig_pe, orig_value;
6115 pe.refclass = klass;
6116 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6117 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6118 FREE_REFENTRY (orig_pe);
6121 mono_domain_unlock (domain);
6124 #ifdef REFENTRY_REQUIRES_CLEANUP
6126 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6128 FREE_REFENTRY (key);
6133 mono_reflection_cleanup_domain (MonoDomain *domain)
6135 if (domain->refobject_hash) {
6136 /*let's avoid scanning the whole hashtable if not needed*/
6137 #ifdef REFENTRY_REQUIRES_CLEANUP
6138 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6140 mono_g_hash_table_destroy (domain->refobject_hash);
6141 domain->refobject_hash = NULL;
6145 #ifndef DISABLE_REFLECTION_EMIT
6147 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6149 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6153 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6155 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6159 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6161 MonoDynamicImage *image = moduleb->dynamic_image;
6162 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6166 MonoImage **new_modules;
6168 char *name, *fqname;
6170 * FIXME: we already created an image in mono_image_basic_init (), but
6171 * we don't know which module it belongs to, since that is only
6172 * determined at assembly save time.
6174 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6175 name = mono_string_to_utf8 (ab->name);
6176 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6177 if (!mono_error_ok (&error)) {
6179 mono_error_raise_exception (&error);
6181 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6183 moduleb->module.image = &image->image;
6184 moduleb->dynamic_image = image;
6185 register_module (mono_object_domain (moduleb), moduleb, image);
6187 /* register the module with the assembly */
6188 ass = ab->dynamic_assembly->assembly.image;
6189 module_count = ass->module_count;
6190 new_modules = g_new0 (MonoImage *, module_count + 1);
6193 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6194 new_modules [module_count] = &image->image;
6195 mono_image_addref (&image->image);
6197 g_free (ass->modules);
6198 ass->modules = new_modules;
6199 ass->module_count ++;
6204 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6206 MonoDynamicImage *image = moduleb->dynamic_image;
6208 g_assert (type->type);
6209 image->wrappers_type = mono_class_from_mono_type (type->type);
6215 * mono_assembly_get_object:
6216 * @domain: an app domain
6217 * @assembly: an assembly
6219 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6221 MonoReflectionAssembly*
6222 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6224 static MonoClass *assembly_type;
6225 MonoReflectionAssembly *res;
6227 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6228 if (!assembly_type) {
6229 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6231 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6233 assembly_type = class;
6235 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6236 res->assembly = assembly;
6238 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6243 MonoReflectionModule*
6244 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6246 static MonoClass *module_type;
6247 MonoReflectionModule *res;
6250 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6252 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6254 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6256 module_type = class;
6258 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6261 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6263 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6264 basename = g_path_get_basename (image->name);
6265 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6266 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6270 if (image->assembly->image == image) {
6271 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6275 if (image->assembly->image->modules) {
6276 for (i = 0; i < image->assembly->image->module_count; i++) {
6277 if (image->assembly->image->modules [i] == image)
6278 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6280 g_assert (res->token);
6284 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6287 MonoReflectionModule*
6288 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6290 static MonoClass *module_type;
6291 MonoReflectionModule *res;
6292 MonoTableInfo *table;
6293 guint32 cols [MONO_FILE_SIZE];
6295 guint32 i, name_idx;
6299 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6301 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6303 module_type = class;
6305 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6307 table = &image->tables [MONO_TABLE_FILE];
6308 g_assert (table_index < table->rows);
6309 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6312 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6313 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6315 /* Check whenever the row has a corresponding row in the moduleref table */
6316 table = &image->tables [MONO_TABLE_MODULEREF];
6317 for (i = 0; i < table->rows; ++i) {
6318 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6319 val = mono_metadata_string_heap (image, name_idx);
6320 if (strcmp (val, name) == 0)
6321 res->image = image->modules [i];
6324 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6325 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6326 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6327 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6328 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6334 verify_safe_for_managed_space (MonoType *type)
6336 switch (type->type) {
6338 case MONO_TYPE_ARRAY:
6339 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6341 return verify_safe_for_managed_space (type->data.type);
6342 case MONO_TYPE_SZARRAY:
6343 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6344 case MONO_TYPE_GENERICINST: {
6345 MonoGenericInst *inst = type->data.generic_class->inst;
6349 for (i = 0; i < inst->type_argc; ++i)
6350 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6356 case MONO_TYPE_MVAR:
6363 mono_type_normalize (MonoType *type)
6366 MonoGenericClass *gclass;
6367 MonoGenericInst *ginst;
6369 MonoGenericContainer *gcontainer;
6370 MonoType **argv = NULL;
6371 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6373 if (type->type != MONO_TYPE_GENERICINST)
6376 gclass = type->data.generic_class;
6377 ginst = gclass->context.class_inst;
6378 if (!ginst->is_open)
6381 gtd = gclass->container_class;
6382 gcontainer = gtd->generic_container;
6383 argv = g_newa (MonoType*, ginst->type_argc);
6385 for (i = 0; i < ginst->type_argc; ++i) {
6386 MonoType *t = ginst->type_argv [i], *norm;
6387 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6388 is_denorm_gtd = FALSE;
6389 norm = mono_type_normalize (t);
6392 requires_rebind = TRUE;
6396 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6398 if (requires_rebind) {
6399 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6400 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6406 * mono_type_get_object:
6407 * @domain: an app domain
6410 * Return an System.MonoType object representing the type @type.
6413 mono_type_get_object (MonoDomain *domain, MonoType *type)
6415 MonoType *norm_type;
6416 MonoReflectionType *res;
6417 MonoClass *klass = mono_class_from_mono_type (type);
6419 /*we must avoid using @type as it might have come
6420 * from a mono_metadata_type_dup and the caller
6421 * expects that is can be freed.
6422 * Using the right type from
6424 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6426 /* void is very common */
6427 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6428 return (MonoReflectionType*)domain->typeof_void;
6431 * If the vtable of the given class was already created, we can use
6432 * the MonoType from there and avoid all locking and hash table lookups.
6434 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6435 * that the resulting object is different.
6437 if (type == &klass->byval_arg && !klass->image->dynamic) {
6438 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6439 if (vtable && vtable->type)
6440 return vtable->type;
6443 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6444 mono_domain_lock (domain);
6445 if (!domain->type_hash)
6446 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6447 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6448 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6449 mono_domain_unlock (domain);
6450 mono_loader_unlock ();
6454 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6455 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6456 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6457 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6458 * artifact of how generics are encoded and should be transparent to managed code so we
6459 * need to weed out this diference when retrieving managed System.Type objects.
6461 norm_type = mono_type_normalize (type);
6462 if (norm_type != type) {
6463 res = mono_type_get_object (domain, norm_type);
6464 mono_g_hash_table_insert (domain->type_hash, type, res);
6465 mono_domain_unlock (domain);
6466 mono_loader_unlock ();
6470 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6471 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6474 if (!verify_safe_for_managed_space (type)) {
6475 mono_domain_unlock (domain);
6476 mono_loader_unlock ();
6477 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6480 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6481 gboolean is_type_done = TRUE;
6482 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6483 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6484 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6486 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6487 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6489 if (gparam->owner && gparam->owner->is_method) {
6490 MonoMethod *method = gparam->owner->owner.method;
6491 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6492 is_type_done = FALSE;
6493 } else if (gparam->owner && !gparam->owner->is_method) {
6494 MonoClass *klass = gparam->owner->owner.klass;
6495 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6496 is_type_done = FALSE;
6500 /* g_assert_not_reached (); */
6501 /* should this be considered an error condition? */
6502 if (is_type_done && !type->byref) {
6503 mono_domain_unlock (domain);
6504 mono_loader_unlock ();
6505 return mono_class_get_ref_info (klass);
6508 /* This is stored in vtables/JITted code so it has to be pinned */
6509 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6511 mono_g_hash_table_insert (domain->type_hash, type, res);
6513 if (type->type == MONO_TYPE_VOID)
6514 domain->typeof_void = (MonoObject*)res;
6516 mono_domain_unlock (domain);
6517 mono_loader_unlock ();
6522 * mono_method_get_object:
6523 * @domain: an app domain
6525 * @refclass: the reflected type (can be NULL)
6527 * Return an System.Reflection.MonoMethod object representing the method @method.
6529 MonoReflectionMethod*
6530 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6533 * We use the same C representation for methods and constructors, but the type
6534 * name in C# is different.
6536 static MonoClass *System_Reflection_MonoMethod = NULL;
6537 static MonoClass *System_Reflection_MonoCMethod = NULL;
6538 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6539 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6541 MonoReflectionMethod *ret;
6543 if (method->is_inflated) {
6544 MonoReflectionGenericMethod *gret;
6546 refclass = method->klass;
6547 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6548 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6549 if (!System_Reflection_MonoGenericCMethod)
6550 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6551 klass = System_Reflection_MonoGenericCMethod;
6553 if (!System_Reflection_MonoGenericMethod)
6554 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6555 klass = System_Reflection_MonoGenericMethod;
6557 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6558 gret->method.method = method;
6559 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6560 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6561 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6565 refclass = method->klass;
6567 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6568 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6569 if (!System_Reflection_MonoCMethod)
6570 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6571 klass = System_Reflection_MonoCMethod;
6574 if (!System_Reflection_MonoMethod)
6575 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6576 klass = System_Reflection_MonoMethod;
6578 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6579 ret->method = method;
6580 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6581 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6585 * mono_method_clear_object:
6587 * Clear the cached reflection objects for the dynamic method METHOD.
6590 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6593 g_assert (method->dynamic);
6595 klass = method->klass;
6597 clear_cached_object (domain, method, klass);
6598 klass = klass->parent;
6600 /* Added by mono_param_get_objects () */
6601 clear_cached_object (domain, &(method->signature), NULL);
6602 klass = method->klass;
6604 clear_cached_object (domain, &(method->signature), klass);
6605 klass = klass->parent;
6610 * mono_field_get_object:
6611 * @domain: an app domain
6615 * Return an System.Reflection.MonoField object representing the field @field
6618 MonoReflectionField*
6619 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6621 MonoReflectionField *res;
6622 static MonoClass *monofield_klass;
6624 CHECK_OBJECT (MonoReflectionField *, field, klass);
6625 if (!monofield_klass)
6626 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6627 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6630 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6632 if (is_field_on_inst (field)) {
6633 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6634 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6637 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6638 res->attrs = mono_field_get_flags (field);
6640 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6644 * mono_property_get_object:
6645 * @domain: an app domain
6647 * @property: a property
6649 * Return an System.Reflection.MonoProperty object representing the property @property
6652 MonoReflectionProperty*
6653 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6655 MonoReflectionProperty *res;
6656 static MonoClass *monoproperty_klass;
6658 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6659 if (!monoproperty_klass)
6660 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6661 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6663 res->property = property;
6664 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6668 * mono_event_get_object:
6669 * @domain: an app domain
6673 * Return an System.Reflection.MonoEvent object representing the event @event
6676 MonoReflectionEvent*
6677 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6679 MonoReflectionEvent *res;
6680 MonoReflectionMonoEvent *mono_event;
6681 static MonoClass *monoevent_klass;
6683 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6684 if (!monoevent_klass)
6685 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6686 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6687 mono_event->klass = klass;
6688 mono_event->event = event;
6689 res = (MonoReflectionEvent*)mono_event;
6690 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6694 * mono_get_reflection_missing_object:
6695 * @domain: Domain where the object lives
6697 * Returns the System.Reflection.Missing.Value singleton object
6698 * (of type System.Reflection.Missing).
6700 * Used as the value for ParameterInfo.DefaultValue when Optional
6704 mono_get_reflection_missing_object (MonoDomain *domain)
6707 static MonoClassField *missing_value_field = NULL;
6709 if (!missing_value_field) {
6710 MonoClass *missing_klass;
6711 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6712 mono_class_init (missing_klass);
6713 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6714 g_assert (missing_value_field);
6716 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6722 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6725 *dbnull = mono_get_dbnull_object (domain);
6730 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6732 if (!*reflection_missing)
6733 *reflection_missing = mono_get_reflection_missing_object (domain);
6734 return *reflection_missing;
6738 * mono_param_get_objects:
6739 * @domain: an app domain
6742 * Return an System.Reflection.ParameterInfo array object representing the parameters
6743 * in the method @method.
6746 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6748 static MonoClass *System_Reflection_ParameterInfo;
6749 static MonoClass *System_Reflection_ParameterInfo_array;
6751 MonoArray *res = NULL;
6752 MonoReflectionMethod *member = NULL;
6753 MonoReflectionParameter *param = NULL;
6754 char **names, **blobs = NULL;
6755 guint32 *types = NULL;
6756 MonoType *type = NULL;
6757 MonoObject *dbnull = NULL;
6758 MonoObject *missing = NULL;
6759 MonoMarshalSpec **mspecs;
6760 MonoMethodSignature *sig;
6761 MonoVTable *pinfo_vtable;
6764 if (!System_Reflection_ParameterInfo_array) {
6767 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6768 mono_memory_barrier ();
6769 System_Reflection_ParameterInfo = klass;
6771 klass = mono_array_class_get (klass, 1);
6772 mono_memory_barrier ();
6773 System_Reflection_ParameterInfo_array = klass;
6776 sig = mono_method_signature_checked (method, &error);
6777 if (!mono_error_ok (&error))
6778 mono_error_raise_exception (&error);
6780 if (!sig->param_count)
6781 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6783 /* Note: the cache is based on the address of the signature into the method
6784 * since we already cache MethodInfos with the method as keys.
6786 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6788 member = mono_method_get_object (domain, method, refclass);
6789 names = g_new (char *, sig->param_count);
6790 mono_method_get_param_names (method, (const char **) names);
6792 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6793 mono_method_get_marshal_info (method, mspecs);
6795 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6796 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6797 for (i = 0; i < sig->param_count; ++i) {
6798 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6799 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6800 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6801 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6802 param->PositionImpl = i;
6803 param->AttrsImpl = sig->params [i]->attrs;
6805 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6806 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6807 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6809 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6813 blobs = g_new0 (char *, sig->param_count);
6814 types = g_new0 (guint32, sig->param_count);
6815 get_default_param_value_blobs (method, blobs, types);
6818 /* Build MonoType for the type from the Constant Table */
6820 type = g_new0 (MonoType, 1);
6821 type->type = types [i];
6822 type->data.klass = NULL;
6823 if (types [i] == MONO_TYPE_CLASS)
6824 type->data.klass = mono_defaults.object_class;
6825 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6826 /* For enums, types [i] contains the base type */
6828 type->type = MONO_TYPE_VALUETYPE;
6829 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6831 type->data.klass = mono_class_from_mono_type (type);
6833 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6835 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6836 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6837 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6838 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6840 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6846 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6848 mono_array_setref (res, i, param);
6855 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6857 mono_metadata_free_marshal_spec (mspecs [i]);
6860 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6864 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6866 return mono_param_get_objects_internal (domain, method, NULL);
6870 * mono_method_body_get_object:
6871 * @domain: an app domain
6874 * Return an System.Reflection.MethodBody object representing the method @method.
6876 MonoReflectionMethodBody*
6877 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6879 static MonoClass *System_Reflection_MethodBody = NULL;
6880 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6881 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6882 MonoReflectionMethodBody *ret;
6883 MonoMethodHeader *header;
6885 guint32 method_rva, local_var_sig_token;
6887 unsigned char format, flags;
6890 /* for compatibility with .net */
6891 if (method->dynamic)
6892 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6894 if (!System_Reflection_MethodBody)
6895 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6896 if (!System_Reflection_LocalVariableInfo)
6897 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6898 if (!System_Reflection_ExceptionHandlingClause)
6899 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6901 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6903 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6904 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6905 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6906 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6909 image = method->klass->image;
6910 header = mono_method_get_header (method);
6912 if (!image->dynamic) {
6913 /* Obtain local vars signature token */
6914 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6915 ptr = mono_image_rva_map (image, method_rva);
6916 flags = *(const unsigned char *) ptr;
6917 format = flags & METHOD_HEADER_FORMAT_MASK;
6919 case METHOD_HEADER_TINY_FORMAT:
6920 local_var_sig_token = 0;
6922 case METHOD_HEADER_FAT_FORMAT:
6926 local_var_sig_token = read32 (ptr);
6929 g_assert_not_reached ();
6932 local_var_sig_token = 0; //FIXME
6934 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6936 ret->init_locals = header->init_locals;
6937 ret->max_stack = header->max_stack;
6938 ret->local_var_sig_token = local_var_sig_token;
6939 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6940 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6943 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6944 for (i = 0; i < header->num_locals; ++i) {
6945 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6946 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6947 info->is_pinned = header->locals [i]->pinned;
6948 info->local_index = i;
6949 mono_array_setref (ret->locals, i, info);
6953 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6954 for (i = 0; i < header->num_clauses; ++i) {
6955 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6956 MonoExceptionClause *clause = &header->clauses [i];
6958 info->flags = clause->flags;
6959 info->try_offset = clause->try_offset;
6960 info->try_length = clause->try_len;
6961 info->handler_offset = clause->handler_offset;
6962 info->handler_length = clause->handler_len;
6963 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6964 info->filter_offset = clause->data.filter_offset;
6965 else if (clause->data.catch_class)
6966 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6968 mono_array_setref (ret->clauses, i, info);
6971 mono_metadata_free_mh (header);
6972 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6977 * mono_get_dbnull_object:
6978 * @domain: Domain where the object lives
6980 * Returns the System.DBNull.Value singleton object
6982 * Used as the value for ParameterInfo.DefaultValue
6985 mono_get_dbnull_object (MonoDomain *domain)
6988 static MonoClassField *dbnull_value_field = NULL;
6990 if (!dbnull_value_field) {
6991 MonoClass *dbnull_klass;
6992 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6993 mono_class_init (dbnull_klass);
6994 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6995 g_assert (dbnull_value_field);
6997 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7003 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7005 guint32 param_index, i, lastp, crow = 0;
7006 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7009 MonoClass *klass = method->klass;
7010 MonoImage *image = klass->image;
7011 MonoMethodSignature *methodsig = mono_method_signature (method);
7013 MonoTableInfo *constt;
7014 MonoTableInfo *methodt;
7015 MonoTableInfo *paramt;
7017 if (!methodsig->param_count)
7020 mono_class_init (klass);
7022 if (klass->image->dynamic) {
7023 MonoReflectionMethodAux *aux;
7024 if (method->is_inflated)
7025 method = ((MonoMethodInflated*)method)->declaring;
7026 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7027 if (aux && aux->param_defaults) {
7028 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7029 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7034 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7035 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7036 constt = &image->tables [MONO_TABLE_CONSTANT];
7038 idx = mono_method_get_index (method) - 1;
7039 g_assert (idx != -1);
7041 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7042 if (idx + 1 < methodt->rows)
7043 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7045 lastp = paramt->rows + 1;
7047 for (i = param_index; i < lastp; ++i) {
7050 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7051 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7053 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7056 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7061 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7062 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7063 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7070 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7075 MonoType *basetype = type;
7080 klass = mono_class_from_mono_type (type);
7081 if (klass->valuetype) {
7082 object = mono_object_new (domain, klass);
7083 retval = ((gchar *) object + sizeof (MonoObject));
7084 if (klass->enumtype)
7085 basetype = mono_class_enum_basetype (klass);
7090 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7097 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7100 gboolean quoted = FALSE;
7102 memset (assembly, 0, sizeof (MonoAssemblyName));
7103 assembly->culture = "";
7104 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7111 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7122 /* Remove trailing whitespace */
7124 while (*s && g_ascii_isspace (*s))
7127 while (g_ascii_isspace (*p))
7130 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7132 assembly->major = strtoul (p, &s, 10);
7133 if (s == p || *s != '.')
7136 assembly->minor = strtoul (p, &s, 10);
7137 if (s == p || *s != '.')
7140 assembly->build = strtoul (p, &s, 10);
7141 if (s == p || *s != '.')
7144 assembly->revision = strtoul (p, &s, 10);
7148 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7150 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7151 assembly->culture = "";
7154 assembly->culture = p;
7155 while (*p && *p != ',') {
7159 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7161 if (strncmp (p, "null", 4) == 0) {
7166 while (*p && *p != ',') {
7169 len = (p - start + 1);
7170 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7171 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7172 g_strlcpy ((char*)assembly->public_key_token, start, len);
7175 while (*p && *p != ',')
7179 while (g_ascii_isspace (*p) || *p == ',') {
7193 * mono_reflection_parse_type:
7196 * Parse a type name as accepted by the GetType () method and output the info
7197 * extracted in the info structure.
7198 * the name param will be mangled, so, make a copy before passing it to this function.
7199 * The fields in info will be valid until the memory pointed to by name is valid.
7201 * See also mono_type_get_name () below.
7203 * Returns: 0 on parse error.
7206 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7207 MonoTypeNameParse *info)
7209 char *start, *p, *w, *temp, *last_point, *startn;
7210 int in_modifiers = 0;
7211 int isbyref = 0, rank, arity = 0, i;
7213 start = p = w = name;
7215 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7216 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7217 info->name = info->name_space = NULL;
7218 info->nested = NULL;
7219 info->modifiers = NULL;
7220 info->type_arguments = NULL;
7222 /* last_point separates the namespace from the name */
7225 while (*p == ' ') p++, start++, w++, name++;
7230 *p = 0; /* NULL terminate the name */
7232 info->nested = g_list_append (info->nested, startn);
7233 /* we have parsed the nesting namespace + name */
7237 info->name_space = start;
7239 info->name = last_point + 1;
7241 info->name_space = (char *)"";
7260 i = strtol (p, &temp, 10);
7277 info->name_space = start;
7279 info->name = last_point + 1;
7281 info->name_space = (char *)"";
7288 if (isbyref) /* only one level allowed by the spec */
7291 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7295 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7301 info->type_arguments = g_ptr_array_new ();
7302 for (i = 0; i < arity; i++) {
7303 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7304 gboolean fqname = FALSE;
7306 g_ptr_array_add (info->type_arguments, subinfo);
7313 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7316 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7317 if (fqname && (*p != ']')) {
7325 while (*p && (*p != ']'))
7333 if (g_ascii_isspace (*aname)) {
7340 !assembly_name_to_aname (&subinfo->assembly, aname))
7342 } else if (fqname && (*p == ']')) {
7346 if (i + 1 < arity) {
7366 else if (*p == '*') /* '*' means unknown lower bound */
7367 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7374 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7385 if (g_ascii_isspace (*p)) {
7392 return 0; /* missing assembly name */
7393 if (!assembly_name_to_aname (&info->assembly, p))
7399 if (info->assembly.name)
7402 // *w = 0; /* terminate class name */
7404 if (!info->name || !*info->name)
7408 /* add other consistency checks */
7413 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7415 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7419 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7421 gboolean type_resolve = FALSE;
7423 MonoImage *rootimage = image;
7425 if (info->assembly.name) {
7426 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7427 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7429 * This could happen in the AOT compiler case when the search hook is not
7432 assembly = image->assembly;
7434 /* then we must load the assembly ourselve - see #60439 */
7435 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7439 image = assembly->image;
7440 } else if (!image) {
7441 image = mono_defaults.corlib;
7444 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7445 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7446 image = mono_defaults.corlib;
7447 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7454 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7459 gboolean bounded = FALSE;
7462 image = mono_defaults.corlib;
7465 klass = mono_class_from_name_case (image, info->name_space, info->name);
7467 klass = mono_class_from_name (image, info->name_space, info->name);
7470 for (mod = info->nested; mod; mod = mod->next) {
7471 gpointer iter = NULL;
7475 mono_class_init (parent);
7477 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7479 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7482 if (strcmp (klass->name, mod->data) == 0)
7492 if (info->type_arguments) {
7493 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7494 MonoReflectionType *the_type;
7498 for (i = 0; i < info->type_arguments->len; i++) {
7499 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7501 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7502 if (!type_args [i]) {
7508 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7510 instance = mono_reflection_bind_generic_parameters (
7511 the_type, info->type_arguments->len, type_args);
7517 klass = mono_class_from_mono_type (instance);
7520 for (mod = info->modifiers; mod; mod = mod->next) {
7521 modval = GPOINTER_TO_UINT (mod->data);
7522 if (!modval) { /* byref: must be last modifier */
7523 return &klass->this_arg;
7524 } else if (modval == -1) {
7525 klass = mono_ptr_class_get (&klass->byval_arg);
7526 } else if (modval == -2) {
7528 } else { /* array rank */
7529 klass = mono_bounded_array_class_get (klass, modval, bounded);
7533 return &klass->byval_arg;
7537 * mono_reflection_get_type:
7538 * @image: a metadata context
7539 * @info: type description structure
7540 * @ignorecase: flag for case-insensitive string compares
7541 * @type_resolve: whenever type resolve was already tried
7543 * Build a MonoType from the type description in @info.
7548 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7549 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7553 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7555 MonoReflectionAssemblyBuilder *abuilder;
7559 g_assert (assembly->dynamic);
7560 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7562 /* Enumerate all modules */
7565 if (abuilder->modules) {
7566 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7567 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7568 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7574 if (!type && abuilder->loaded_modules) {
7575 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7576 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7577 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7587 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7590 MonoReflectionAssembly *assembly;
7594 if (image && image->dynamic)
7595 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7597 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7600 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7607 *type_resolve = TRUE;
7610 /* Reconstruct the type name */
7611 fullName = g_string_new ("");
7612 if (info->name_space && (info->name_space [0] != '\0'))
7613 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7615 g_string_printf (fullName, "%s", info->name);
7616 for (mod = info->nested; mod; mod = mod->next)
7617 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7619 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7621 if (assembly->assembly->dynamic)
7622 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7624 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7627 g_string_free (fullName, TRUE);
7632 mono_reflection_free_type_info (MonoTypeNameParse *info)
7634 g_list_free (info->modifiers);
7635 g_list_free (info->nested);
7637 if (info->type_arguments) {
7640 for (i = 0; i < info->type_arguments->len; i++) {
7641 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7643 mono_reflection_free_type_info (subinfo);
7644 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7648 g_ptr_array_free (info->type_arguments, TRUE);
7653 * mono_reflection_type_from_name:
7655 * @image: a metadata context (can be NULL).
7657 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7658 * it defaults to get the type from @image or, if @image is NULL or loading
7659 * from it fails, uses corlib.
7663 mono_reflection_type_from_name (char *name, MonoImage *image)
7665 MonoType *type = NULL;
7666 MonoTypeNameParse info;
7669 /* Make a copy since parse_type modifies its argument */
7670 tmp = g_strdup (name);
7672 /*g_print ("requested type %s\n", str);*/
7673 if (mono_reflection_parse_type (tmp, &info)) {
7674 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7678 mono_reflection_free_type_info (&info);
7683 * mono_reflection_get_token:
7685 * Return the metadata token of OBJ which should be an object
7686 * representing a metadata element.
7689 mono_reflection_get_token (MonoObject *obj)
7694 klass = obj->vtable->klass;
7696 if (strcmp (klass->name, "MethodBuilder") == 0) {
7697 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7699 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7700 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7701 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7703 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7704 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7705 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7707 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7708 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7709 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7710 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7711 } else if (strcmp (klass->name, "MonoType") == 0) {
7712 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7713 MonoClass *mc = mono_class_from_mono_type (type);
7714 if (!mono_class_init (mc))
7715 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7717 token = mc->type_token;
7718 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7719 strcmp (klass->name, "MonoMethod") == 0 ||
7720 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7721 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7722 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7723 if (m->method->is_inflated) {
7724 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7725 return inflated->declaring->token;
7727 token = m->method->token;
7729 } else if (strcmp (klass->name, "MonoField") == 0) {
7730 MonoReflectionField *f = (MonoReflectionField*)obj;
7732 if (is_field_on_inst (f->field)) {
7733 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7734 int field_index = f->field - dgclass->fields;
7737 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7738 obj = dgclass->field_objects [field_index];
7739 return mono_reflection_get_token (obj);
7741 token = mono_class_get_field_token (f->field);
7742 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7743 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7745 token = mono_class_get_property_token (p->property);
7746 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7747 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7749 token = mono_class_get_event_token (p->event);
7750 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7751 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7752 MonoClass *member_class = mono_object_class (p->MemberImpl);
7753 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7755 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7756 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7757 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7760 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7761 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7763 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7764 MonoException *ex = mono_get_exception_not_implemented (msg);
7766 mono_raise_exception (ex);
7773 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7775 int slen, type = t->type;
7776 MonoClass *tklass = t->data.klass;
7782 case MONO_TYPE_BOOLEAN: {
7783 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7788 case MONO_TYPE_CHAR:
7790 case MONO_TYPE_I2: {
7791 guint16 *val = g_malloc (sizeof (guint16));
7796 #if SIZEOF_VOID_P == 4
7802 case MONO_TYPE_I4: {
7803 guint32 *val = g_malloc (sizeof (guint32));
7808 #if SIZEOF_VOID_P == 8
7809 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7813 case MONO_TYPE_I8: {
7814 guint64 *val = g_malloc (sizeof (guint64));
7819 case MONO_TYPE_R8: {
7820 double *val = g_malloc (sizeof (double));
7825 case MONO_TYPE_VALUETYPE:
7826 if (t->data.klass->enumtype) {
7827 type = mono_class_enum_basetype (t->data.klass)->type;
7830 MonoClass *k = t->data.klass;
7832 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7833 guint64 *val = g_malloc (sizeof (guint64));
7839 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7842 case MONO_TYPE_STRING:
7843 if (*p == (char)0xFF) {
7847 slen = mono_metadata_decode_value (p, &p);
7849 return mono_string_new_len (mono_domain_get (), p, slen);
7850 case MONO_TYPE_CLASS: {
7853 if (*p == (char)0xFF) {
7858 slen = mono_metadata_decode_value (p, &p);
7859 n = g_memdup (p, slen + 1);
7861 t = mono_reflection_type_from_name (n, image);
7863 g_warning ("Cannot load type '%s'", n);
7867 return mono_type_get_object (mono_domain_get (), t);
7871 case MONO_TYPE_OBJECT: {
7874 MonoClass *subc = NULL;
7879 } else if (subt == 0x0E) {
7880 type = MONO_TYPE_STRING;
7882 } else if (subt == 0x1D) {
7883 MonoType simple_type = {{0}};
7887 type = MONO_TYPE_SZARRAY;
7888 if (etype == 0x50) {
7889 tklass = mono_defaults.systemtype_class;
7892 /* See Partition II, Appendix B3 */
7893 etype = MONO_TYPE_OBJECT;
7894 simple_type.type = etype;
7895 tklass = mono_class_from_mono_type (&simple_type);
7898 } else if (subt == 0x55) {
7901 slen = mono_metadata_decode_value (p, &p);
7902 n = g_memdup (p, slen + 1);
7904 t = mono_reflection_type_from_name (n, image);
7906 g_error ("Cannot load type '%s'", n);
7909 subc = mono_class_from_mono_type (t);
7910 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7911 MonoType simple_type = {{0}};
7912 simple_type.type = subt;
7913 subc = mono_class_from_mono_type (&simple_type);
7915 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7917 val = load_cattr_value (image, &subc->byval_arg, p, end);
7918 obj = mono_object_new (mono_domain_get (), subc);
7919 g_assert (!subc->has_references);
7920 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7924 case MONO_TYPE_SZARRAY: {
7926 guint32 i, alen, basetype;
7929 if (alen == 0xffffffff) {
7933 arr = mono_array_new (mono_domain_get(), tklass, alen);
7934 basetype = tklass->byval_arg.type;
7935 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7936 basetype = mono_class_enum_basetype (tklass)->type;
7941 case MONO_TYPE_BOOLEAN:
7942 for (i = 0; i < alen; i++) {
7943 MonoBoolean val = *p++;
7944 mono_array_set (arr, MonoBoolean, i, val);
7947 case MONO_TYPE_CHAR:
7950 for (i = 0; i < alen; i++) {
7951 guint16 val = read16 (p);
7952 mono_array_set (arr, guint16, i, val);
7959 for (i = 0; i < alen; i++) {
7960 guint32 val = read32 (p);
7961 mono_array_set (arr, guint32, i, val);
7966 for (i = 0; i < alen; i++) {
7969 mono_array_set (arr, double, i, val);
7975 for (i = 0; i < alen; i++) {
7976 guint64 val = read64 (p);
7977 mono_array_set (arr, guint64, i, val);
7981 case MONO_TYPE_CLASS:
7982 case MONO_TYPE_OBJECT:
7983 case MONO_TYPE_STRING:
7984 for (i = 0; i < alen; i++) {
7985 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7986 mono_array_setref (arr, i, item);
7990 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7996 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8002 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8004 static MonoClass *klass;
8005 static MonoMethod *ctor;
8007 void *params [2], *unboxed;
8010 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8012 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8014 params [0] = mono_type_get_object (mono_domain_get (), t);
8016 retval = mono_object_new (mono_domain_get (), klass);
8017 unboxed = mono_object_unbox (retval);
8018 mono_runtime_invoke (ctor, unboxed, params, NULL);
8024 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8026 static MonoClass *klass;
8027 static MonoMethod *ctor;
8029 void *unboxed, *params [2];
8032 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8034 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8037 params [1] = typedarg;
8038 retval = mono_object_new (mono_domain_get (), klass);
8039 unboxed = mono_object_unbox (retval);
8040 mono_runtime_invoke (ctor, unboxed, params, NULL);
8046 type_is_reference (MonoType *type)
8048 switch (type->type) {
8049 case MONO_TYPE_BOOLEAN:
8050 case MONO_TYPE_CHAR:
8063 case MONO_TYPE_VALUETYPE:
8071 free_param_data (MonoMethodSignature *sig, void **params) {
8073 for (i = 0; i < sig->param_count; ++i) {
8074 if (!type_is_reference (sig->params [i]))
8075 g_free (params [i]);
8080 * Find the field index in the metadata FieldDef table.
8083 find_field_index (MonoClass *klass, MonoClassField *field) {
8086 for (i = 0; i < klass->field.count; ++i) {
8087 if (field == &klass->fields [i])
8088 return klass->field.first + 1 + i;
8094 * Find the property index in the metadata Property table.
8097 find_property_index (MonoClass *klass, MonoProperty *property) {
8100 for (i = 0; i < klass->ext->property.count; ++i) {
8101 if (property == &klass->ext->properties [i])
8102 return klass->ext->property.first + 1 + i;
8108 * Find the event index in the metadata Event table.
8111 find_event_index (MonoClass *klass, MonoEvent *event) {
8114 for (i = 0; i < klass->ext->event.count; ++i) {
8115 if (event == &klass->ext->events [i])
8116 return klass->ext->event.first + 1 + i;
8122 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8124 const char *p = (const char*)data;
8126 guint32 i, j, num_named;
8128 void *params_buf [32];
8130 MonoMethodSignature *sig;
8132 mono_error_init (error);
8134 mono_class_init (method->klass);
8136 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8137 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8142 attr = mono_object_new (mono_domain_get (), method->klass);
8143 mono_runtime_invoke (method, attr, NULL, NULL);
8147 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8150 /*g_print ("got attr %s\n", method->klass->name);*/
8152 sig = mono_method_signature (method);
8153 if (sig->param_count < 32)
8154 params = params_buf;
8156 /* Allocate using GC so it gets GC tracking */
8157 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8161 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8162 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8166 attr = mono_object_new (mono_domain_get (), method->klass);
8167 mono_runtime_invoke (method, attr, params, NULL);
8168 free_param_data (method->signature, params);
8169 num_named = read16 (named);
8171 for (j = 0; j < num_named; j++) {
8173 char *name, named_type, data_type;
8174 named_type = *named++;
8175 data_type = *named++; /* type of data */
8176 if (data_type == MONO_TYPE_SZARRAY)
8177 data_type = *named++;
8178 if (data_type == MONO_TYPE_ENUM) {
8181 type_len = mono_metadata_decode_blob_size (named, &named);
8182 type_name = g_malloc (type_len + 1);
8183 memcpy (type_name, named, type_len);
8184 type_name [type_len] = 0;
8186 /* FIXME: lookup the type and check type consistency */
8189 name_len = mono_metadata_decode_blob_size (named, &named);
8190 name = g_malloc (name_len + 1);
8191 memcpy (name, named, name_len);
8192 name [name_len] = 0;
8194 if (named_type == 0x53) {
8195 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8196 void *val = load_cattr_value (image, field->type, named, &named);
8197 mono_field_set_value (attr, field, val);
8198 if (!type_is_reference (field->type))
8200 } else if (named_type == 0x54) {
8203 MonoType *prop_type;
8205 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8206 /* can we have more that 1 arg in a custom attr named property? */
8207 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8208 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8209 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8210 mono_property_set_value (prop, attr, pparams, NULL);
8211 if (!type_is_reference (prop_type))
8212 g_free (pparams [0]);
8217 if (params != params_buf)
8218 mono_gc_free_fixed (params);
8224 * mono_reflection_create_custom_attr_data_args:
8226 * Create an array of typed and named arguments from the cattr blob given by DATA.
8227 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8228 * NAMED_ARG_INFO will contain information about the named arguments.
8231 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)
8233 MonoArray *typedargs, *namedargs;
8234 MonoClass *attrklass;
8236 const char *p = (const char*)data;
8238 guint32 i, j, num_named;
8239 CattrNamedArg *arginfo = NULL;
8241 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8244 mono_class_init (method->klass);
8248 *named_arg_info = NULL;
8250 domain = mono_domain_get ();
8252 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8255 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8259 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8263 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8264 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8265 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8266 mono_array_setref (typedargs, i, obj);
8268 if (!type_is_reference (mono_method_signature (method)->params [i]))
8273 num_named = read16 (named);
8274 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8276 attrklass = method->klass;
8278 arginfo = g_new0 (CattrNamedArg, num_named);
8279 *named_arg_info = arginfo;
8281 for (j = 0; j < num_named; j++) {
8283 char *name, named_type, data_type;
8284 named_type = *named++;
8285 data_type = *named++; /* type of data */
8286 if (data_type == MONO_TYPE_SZARRAY)
8287 data_type = *named++;
8288 if (data_type == MONO_TYPE_ENUM) {
8291 type_len = mono_metadata_decode_blob_size (named, &named);
8292 type_name = g_malloc (type_len + 1);
8293 memcpy (type_name, named, type_len);
8294 type_name [type_len] = 0;
8296 /* FIXME: lookup the type and check type consistency */
8299 name_len = mono_metadata_decode_blob_size (named, &named);
8300 name = g_malloc (name_len + 1);
8301 memcpy (name, named, name_len);
8302 name [name_len] = 0;
8304 if (named_type == 0x53) {
8306 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8309 arginfo [j].type = field->type;
8310 arginfo [j].field = field;
8312 val = load_cattr_value (image, field->type, named, &named);
8313 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8314 mono_array_setref (namedargs, j, obj);
8315 if (!type_is_reference (field->type))
8317 } else if (named_type == 0x54) {
8319 MonoType *prop_type;
8320 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8323 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8324 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8326 arginfo [j].type = prop_type;
8327 arginfo [j].prop = prop;
8329 val = load_cattr_value (image, prop_type, named, &named);
8330 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8331 mono_array_setref (namedargs, j, obj);
8332 if (!type_is_reference (prop_type))
8338 *typed_args = typedargs;
8339 *named_args = namedargs;
8343 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8346 MonoArray *typedargs, *namedargs;
8349 CattrNamedArg *arginfo;
8358 image = assembly->assembly->image;
8359 method = ref_method->method;
8360 domain = mono_object_domain (ref_method);
8362 if (!mono_class_init (method->klass))
8363 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8365 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8366 if (mono_loader_get_last_error ())
8367 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8369 if (!typedargs || !namedargs)
8372 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8373 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8374 MonoObject *typedarg;
8376 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8377 mono_array_setref (typedargs, i, typedarg);
8380 for (i = 0; i < mono_array_length (namedargs); ++i) {
8381 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8382 MonoObject *typedarg, *namedarg, *minfo;
8384 if (arginfo [i].prop)
8385 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8387 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8389 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8390 namedarg = create_cattr_named_arg (minfo, typedarg);
8392 mono_array_setref (namedargs, i, namedarg);
8395 *ctor_args = typedargs;
8396 *named_args = namedargs;
8400 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8402 static MonoMethod *ctor;
8407 g_assert (image->assembly);
8410 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8412 domain = mono_domain_get ();
8413 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8414 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8415 params [1] = mono_assembly_get_object (domain, image->assembly);
8416 params [2] = (gpointer)&cattr->data;
8417 params [3] = &cattr->data_size;
8418 mono_runtime_invoke (ctor, attr, params, NULL);
8423 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8429 mono_error_init (error);
8432 for (i = 0; i < cinfo->num_attrs; ++i) {
8433 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8437 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8439 for (i = 0; i < cinfo->num_attrs; ++i) {
8440 if (!cinfo->attrs [i].ctor)
8441 /* The cattr type is not finished yet */
8442 /* We should include the type name but cinfo doesn't contain it */
8443 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8444 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8445 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8446 if (!mono_error_ok (error))
8448 mono_array_setref (result, n, attr);
8456 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8460 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8464 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8470 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8471 for (i = 0; i < cinfo->num_attrs; ++i) {
8472 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8473 mono_array_setref (result, i, attr);
8479 * mono_custom_attrs_from_index:
8481 * Returns: NULL if no attributes are found or if a loading error occurs.
8484 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8486 guint32 mtoken, i, len;
8487 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8489 MonoCustomAttrInfo *ainfo;
8490 GList *tmp, *list = NULL;
8493 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8495 i = mono_metadata_custom_attrs_from_index (image, idx);
8499 while (i < ca->rows) {
8500 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8502 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8505 len = g_list_length (list);
8508 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8509 ainfo->num_attrs = len;
8510 ainfo->image = image;
8511 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8512 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8513 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8514 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8515 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8516 mtoken |= MONO_TOKEN_METHOD_DEF;
8518 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8519 mtoken |= MONO_TOKEN_MEMBER_REF;
8522 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8525 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8526 if (!ainfo->attrs [i].ctor) {
8527 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8533 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8534 /*FIXME raising an exception here doesn't make any sense*/
8535 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8540 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8541 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8542 ainfo->attrs [i].data = (guchar*)data;
8550 mono_custom_attrs_from_method (MonoMethod *method)
8555 * An instantiated method has the same cattrs as the generic method definition.
8557 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8558 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8560 if (method->is_inflated)
8561 method = ((MonoMethodInflated *) method)->declaring;
8563 if (method->dynamic || method->klass->image->dynamic)
8564 return lookup_custom_attr (method->klass->image, method);
8567 /* Synthetic methods */
8570 idx = mono_method_get_index (method);
8571 idx <<= MONO_CUSTOM_ATTR_BITS;
8572 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8573 return mono_custom_attrs_from_index (method->klass->image, idx);
8577 mono_custom_attrs_from_class (MonoClass *klass)
8581 if (klass->generic_class)
8582 klass = klass->generic_class->container_class;
8584 if (klass->image->dynamic)
8585 return lookup_custom_attr (klass->image, klass);
8587 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8588 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8589 idx <<= MONO_CUSTOM_ATTR_BITS;
8590 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8592 idx = mono_metadata_token_index (klass->type_token);
8593 idx <<= MONO_CUSTOM_ATTR_BITS;
8594 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8596 return mono_custom_attrs_from_index (klass->image, idx);
8600 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8604 if (assembly->image->dynamic)
8605 return lookup_custom_attr (assembly->image, assembly);
8606 idx = 1; /* there is only one assembly */
8607 idx <<= MONO_CUSTOM_ATTR_BITS;
8608 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8609 return mono_custom_attrs_from_index (assembly->image, idx);
8612 static MonoCustomAttrInfo*
8613 mono_custom_attrs_from_module (MonoImage *image)
8618 return lookup_custom_attr (image, image);
8619 idx = 1; /* there is only one module */
8620 idx <<= MONO_CUSTOM_ATTR_BITS;
8621 idx |= MONO_CUSTOM_ATTR_MODULE;
8622 return mono_custom_attrs_from_index (image, idx);
8626 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8630 if (klass->image->dynamic) {
8631 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8632 return lookup_custom_attr (klass->image, property);
8634 idx = find_property_index (klass, property);
8635 idx <<= MONO_CUSTOM_ATTR_BITS;
8636 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8637 return mono_custom_attrs_from_index (klass->image, idx);
8641 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8645 if (klass->image->dynamic) {
8646 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8647 return lookup_custom_attr (klass->image, event);
8649 idx = find_event_index (klass, event);
8650 idx <<= MONO_CUSTOM_ATTR_BITS;
8651 idx |= MONO_CUSTOM_ATTR_EVENT;
8652 return mono_custom_attrs_from_index (klass->image, idx);
8656 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8659 if (klass->image->dynamic) {
8660 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8661 return lookup_custom_attr (klass->image, field);
8663 idx = find_field_index (klass, field);
8664 idx <<= MONO_CUSTOM_ATTR_BITS;
8665 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8666 return mono_custom_attrs_from_index (klass->image, idx);
8670 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8673 guint32 i, idx, method_index;
8674 guint32 param_list, param_last, param_pos, found;
8676 MonoReflectionMethodAux *aux;
8679 * An instantiated method has the same cattrs as the generic method definition.
8681 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8682 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8684 if (method->is_inflated)
8685 method = ((MonoMethodInflated *) method)->declaring;
8687 if (method->klass->image->dynamic) {
8688 MonoCustomAttrInfo *res, *ainfo;
8691 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8692 if (!aux || !aux->param_cattr)
8695 /* Need to copy since it will be freed later */
8696 ainfo = aux->param_cattr [param];
8699 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8700 res = g_malloc0 (size);
8701 memcpy (res, ainfo, size);
8705 image = method->klass->image;
8706 method_index = mono_method_get_index (method);
8709 ca = &image->tables [MONO_TABLE_METHOD];
8711 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8712 if (method_index == ca->rows) {
8713 ca = &image->tables [MONO_TABLE_PARAM];
8714 param_last = ca->rows + 1;
8716 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8717 ca = &image->tables [MONO_TABLE_PARAM];
8720 for (i = param_list; i < param_last; ++i) {
8721 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8722 if (param_pos == param) {
8730 idx <<= MONO_CUSTOM_ATTR_BITS;
8731 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8732 return mono_custom_attrs_from_index (image, idx);
8736 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8740 for (i = 0; i < ainfo->num_attrs; ++i) {
8741 klass = ainfo->attrs [i].ctor->klass;
8742 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8749 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8756 for (i = 0; i < ainfo->num_attrs; ++i) {
8757 klass = ainfo->attrs [i].ctor->klass;
8758 if (mono_class_has_parent (klass, attr_klass)) {
8763 if (attr_index == -1)
8766 attrs = mono_custom_attrs_construct (ainfo);
8768 return mono_array_get (attrs, MonoObject*, attr_index);
8774 * mono_reflection_get_custom_attrs_info:
8775 * @obj: a reflection object handle
8777 * Return the custom attribute info for attributes defined for the
8778 * reflection handle @obj. The objects.
8780 * FIXME this function leaks like a sieve for SRE objects.
8783 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8786 MonoCustomAttrInfo *cinfo = NULL;
8788 klass = obj->vtable->klass;
8789 if (klass == mono_defaults.monotype_class) {
8790 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8791 klass = mono_class_from_mono_type (type);
8792 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8793 cinfo = mono_custom_attrs_from_class (klass);
8794 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8795 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8796 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8797 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8798 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8799 cinfo = mono_custom_attrs_from_module (module->image);
8800 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8801 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8802 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8803 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8804 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8805 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8806 } else if (strcmp ("MonoField", klass->name) == 0) {
8807 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8808 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8809 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8810 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8811 cinfo = mono_custom_attrs_from_method (rmethod->method);
8812 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8813 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8814 cinfo = mono_custom_attrs_from_method (rmethod->method);
8815 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8816 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8817 MonoClass *member_class = mono_object_class (param->MemberImpl);
8818 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8819 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8820 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8821 } else if (is_sr_mono_property (member_class)) {
8822 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8824 if (!(method = prop->property->get))
8825 method = prop->property->set;
8828 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8830 #ifndef DISABLE_REFLECTION_EMIT
8831 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8832 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8833 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8834 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8835 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8836 MonoMethod *method = NULL;
8837 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8838 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8839 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8840 method = ((MonoReflectionMethod *)c->cb)->method;
8842 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));
8844 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8848 char *type_name = mono_type_get_full_name (member_class);
8849 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8850 MonoException *ex = mono_get_exception_not_supported (msg);
8853 mono_raise_exception (ex);
8855 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8856 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8857 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8858 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8859 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8860 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8861 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8862 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8863 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8864 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8865 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8866 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8867 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8868 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8869 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8870 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8871 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8872 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8873 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8874 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8875 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8876 } else { /* handle other types here... */
8877 g_error ("get custom attrs not yet supported for %s", klass->name);
8884 * mono_reflection_get_custom_attrs_by_type:
8885 * @obj: a reflection object handle
8887 * Return an array with all the custom attributes defined of the
8888 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8889 * of that type are returned. The objects are fully build. Return NULL if a loading error
8893 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8896 MonoCustomAttrInfo *cinfo;
8898 mono_error_init (error);
8900 cinfo = mono_reflection_get_custom_attrs_info (obj);
8902 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8904 mono_custom_attrs_free (cinfo);
8906 if (mono_loader_get_last_error ())
8908 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8915 * mono_reflection_get_custom_attrs:
8916 * @obj: a reflection object handle
8918 * Return an array with all the custom attributes defined of the
8919 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8923 mono_reflection_get_custom_attrs (MonoObject *obj)
8927 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8931 * mono_reflection_get_custom_attrs_data:
8932 * @obj: a reflection obj handle
8934 * Returns an array of System.Reflection.CustomAttributeData,
8935 * which include information about attributes reflected on
8936 * types loaded using the Reflection Only methods
8939 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8942 MonoCustomAttrInfo *cinfo;
8944 cinfo = mono_reflection_get_custom_attrs_info (obj);
8946 result = mono_custom_attrs_data_construct (cinfo);
8948 mono_custom_attrs_free (cinfo);
8950 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8955 static MonoReflectionType*
8956 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8958 static MonoMethod *method_get_underlying_system_type = NULL;
8959 MonoMethod *usertype_method;
8961 if (!method_get_underlying_system_type)
8962 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8963 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8964 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8969 is_corlib_type (MonoClass *class)
8971 return class->image == mono_defaults.corlib;
8974 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8975 static MonoClass *cached_class; \
8977 return cached_class == _class; \
8978 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8979 cached_class = _class; \
8986 #ifndef DISABLE_REFLECTION_EMIT
8988 is_sre_array (MonoClass *class)
8990 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8994 is_sre_byref (MonoClass *class)
8996 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9000 is_sre_pointer (MonoClass *class)
9002 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9006 is_sre_generic_instance (MonoClass *class)
9008 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9012 is_sre_type_builder (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9018 is_sre_method_builder (MonoClass *class)
9020 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9024 is_sre_ctor_builder (MonoClass *class)
9026 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9030 is_sre_field_builder (MonoClass *class)
9032 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9036 is_sre_method_on_tb_inst (MonoClass *class)
9038 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9042 is_sre_ctor_on_tb_inst (MonoClass *class)
9044 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9048 mono_reflection_type_get_handle (MonoReflectionType* ref)
9056 if (is_usertype (ref)) {
9057 ref = mono_reflection_type_get_underlying_system_type (ref);
9058 if (ref == NULL || is_usertype (ref))
9064 class = mono_object_class (ref);
9066 if (is_sre_array (class)) {
9068 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9069 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9071 if (sre_array->rank == 0) //single dimentional array
9072 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9074 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9075 sre_array->type.type = res;
9077 } else if (is_sre_byref (class)) {
9079 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9080 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9082 res = &mono_class_from_mono_type (base)->this_arg;
9083 sre_byref->type.type = res;
9085 } else if (is_sre_pointer (class)) {
9087 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9088 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9090 res = &mono_ptr_class_get (base)->byval_arg;
9091 sre_pointer->type.type = res;
9093 } else if (is_sre_generic_instance (class)) {
9094 MonoType *res, **types;
9095 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9098 count = mono_array_length (gclass->type_arguments);
9099 types = g_new0 (MonoType*, count);
9100 for (i = 0; i < count; ++i) {
9101 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9102 types [i] = mono_reflection_type_get_handle (t);
9109 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9112 gclass->type.type = res;
9116 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9123 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9125 mono_reflection_type_get_handle (type);
9129 mono_reflection_register_with_runtime (MonoReflectionType *type)
9131 MonoType *res = mono_reflection_type_get_handle (type);
9132 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9136 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9138 class = mono_class_from_mono_type (res);
9140 mono_loader_lock (); /*same locking as mono_type_get_object*/
9141 mono_domain_lock (domain);
9143 if (!class->image->dynamic) {
9144 mono_class_setup_supertypes (class);
9146 if (!domain->type_hash)
9147 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9148 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9149 mono_g_hash_table_insert (domain->type_hash, res, type);
9151 mono_domain_unlock (domain);
9152 mono_loader_unlock ();
9156 * LOCKING: Assumes the loader lock is held.
9158 static MonoMethodSignature*
9159 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9160 MonoMethodSignature *sig;
9163 count = parameters? mono_array_length (parameters): 0;
9165 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9166 sig->param_count = count;
9167 sig->sentinelpos = -1; /* FIXME */
9168 for (i = 0; i < count; ++i)
9169 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9174 * LOCKING: Assumes the loader lock is held.
9176 static MonoMethodSignature*
9177 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9178 MonoMethodSignature *sig;
9180 sig = parameters_to_signature (image, ctor->parameters);
9181 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9182 sig->ret = &mono_defaults.void_class->byval_arg;
9187 * LOCKING: Assumes the loader lock is held.
9189 static MonoMethodSignature*
9190 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9191 MonoMethodSignature *sig;
9193 sig = parameters_to_signature (image, method->parameters);
9194 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9195 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9196 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9200 static MonoMethodSignature*
9201 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9202 MonoMethodSignature *sig;
9204 sig = parameters_to_signature (NULL, method->parameters);
9205 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9206 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9207 sig->generic_param_count = 0;
9212 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9214 MonoClass *klass = mono_object_class (prop);
9215 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9216 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9217 *name = mono_string_to_utf8 (pb->name);
9218 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9220 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9221 *name = g_strdup (p->property->name);
9222 if (p->property->get)
9223 *type = mono_method_signature (p->property->get)->ret;
9225 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9230 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9232 MonoClass *klass = mono_object_class (field);
9233 if (strcmp (klass->name, "FieldBuilder") == 0) {
9234 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9235 *name = mono_string_to_utf8 (fb->name);
9236 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9238 MonoReflectionField *f = (MonoReflectionField *)field;
9239 *name = g_strdup (mono_field_get_name (f->field));
9240 *type = f->field->type;
9244 #else /* DISABLE_REFLECTION_EMIT */
9247 mono_reflection_register_with_runtime (MonoReflectionType *type)
9253 is_sre_type_builder (MonoClass *class)
9259 is_sre_generic_instance (MonoClass *class)
9265 init_type_builder_generics (MonoObject *type)
9269 #endif /* !DISABLE_REFLECTION_EMIT */
9273 is_sr_mono_field (MonoClass *class)
9275 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9279 is_sr_mono_property (MonoClass *class)
9281 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9285 is_sr_mono_method (MonoClass *class)
9287 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9291 is_sr_mono_cmethod (MonoClass *class)
9293 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9297 is_sr_mono_generic_method (MonoClass *class)
9299 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9303 is_sr_mono_generic_cmethod (MonoClass *class)
9305 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9309 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9311 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9315 is_usertype (MonoReflectionType *ref)
9317 MonoClass *class = mono_object_class (ref);
9318 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9321 static MonoReflectionType*
9322 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9324 if (!type || type->type)
9327 if (is_usertype (type)) {
9328 type = mono_reflection_type_get_underlying_system_type (type);
9329 if (is_usertype (type))
9330 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9336 * Encode a value in a custom attribute stream of bytes.
9337 * The value to encode is either supplied as an object in argument val
9338 * (valuetypes are boxed), or as a pointer to the data in the
9340 * @type represents the type of the value
9341 * @buffer is the start of the buffer
9342 * @p the current position in the buffer
9343 * @buflen contains the size of the buffer and is used to return the new buffer size
9344 * if this needs to be realloced.
9345 * @retbuffer and @retp return the start and the position of the buffer
9348 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9350 MonoTypeEnum simple_type;
9352 if ((p-buffer) + 10 >= *buflen) {
9355 newbuf = g_realloc (buffer, *buflen);
9356 p = newbuf + (p-buffer);
9360 argval = ((char*)arg + sizeof (MonoObject));
9361 simple_type = type->type;
9363 switch (simple_type) {
9364 case MONO_TYPE_BOOLEAN:
9369 case MONO_TYPE_CHAR:
9372 swap_with_size (p, argval, 2, 1);
9378 swap_with_size (p, argval, 4, 1);
9382 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9392 swap_with_size (p, argval, 8, 1);
9398 swap_with_size (p, argval, 8, 1);
9401 case MONO_TYPE_VALUETYPE:
9402 if (type->data.klass->enumtype) {
9403 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9406 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9409 case MONO_TYPE_STRING: {
9416 str = mono_string_to_utf8 ((MonoString*)arg);
9417 slen = strlen (str);
9418 if ((p-buffer) + 10 + slen >= *buflen) {
9422 newbuf = g_realloc (buffer, *buflen);
9423 p = newbuf + (p-buffer);
9426 mono_metadata_encode_value (slen, p, &p);
9427 memcpy (p, str, slen);
9432 case MONO_TYPE_CLASS: {
9440 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9441 slen = strlen (str);
9442 if ((p-buffer) + 10 + slen >= *buflen) {
9446 newbuf = g_realloc (buffer, *buflen);
9447 p = newbuf + (p-buffer);
9450 mono_metadata_encode_value (slen, p, &p);
9451 memcpy (p, str, slen);
9456 case MONO_TYPE_SZARRAY: {
9458 MonoClass *eclass, *arg_eclass;
9461 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9464 len = mono_array_length ((MonoArray*)arg);
9466 *p++ = (len >> 8) & 0xff;
9467 *p++ = (len >> 16) & 0xff;
9468 *p++ = (len >> 24) & 0xff;
9470 *retbuffer = buffer;
9471 eclass = type->data.klass;
9472 arg_eclass = mono_object_class (arg)->element_class;
9475 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9476 eclass = mono_defaults.object_class;
9478 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9479 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9480 int elsize = mono_class_array_element_size (arg_eclass);
9481 for (i = 0; i < len; ++i) {
9482 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9485 } else if (eclass->valuetype && arg_eclass->valuetype) {
9486 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9487 int elsize = mono_class_array_element_size (eclass);
9488 for (i = 0; i < len; ++i) {
9489 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9493 for (i = 0; i < len; ++i) {
9494 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9499 case MONO_TYPE_OBJECT: {
9505 * The parameter type is 'object' but the type of the actual
9506 * argument is not. So we have to add type information to the blob
9507 * too. This is completely undocumented in the spec.
9511 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9516 klass = mono_object_class (arg);
9518 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9521 } else if (klass->enumtype) {
9523 } else if (klass == mono_defaults.string_class) {
9524 simple_type = MONO_TYPE_STRING;
9527 } else if (klass->rank == 1) {
9529 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9530 /* See Partition II, Appendix B3 */
9533 *p++ = klass->element_class->byval_arg.type;
9534 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9536 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9537 *p++ = simple_type = klass->byval_arg.type;
9540 g_error ("unhandled type in custom attr");
9542 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9543 slen = strlen (str);
9544 if ((p-buffer) + 10 + slen >= *buflen) {
9548 newbuf = g_realloc (buffer, *buflen);
9549 p = newbuf + (p-buffer);
9552 mono_metadata_encode_value (slen, p, &p);
9553 memcpy (p, str, slen);
9556 simple_type = mono_class_enum_basetype (klass)->type;
9560 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9563 *retbuffer = buffer;
9567 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9569 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9570 char *str = type_get_qualified_name (type, NULL);
9571 int slen = strlen (str);
9575 * This seems to be optional...
9578 mono_metadata_encode_value (slen, p, &p);
9579 memcpy (p, str, slen);
9582 } else if (type->type == MONO_TYPE_OBJECT) {
9584 } else if (type->type == MONO_TYPE_CLASS) {
9585 /* it should be a type: encode_cattr_value () has the check */
9588 mono_metadata_encode_value (type->type, p, &p);
9589 if (type->type == MONO_TYPE_SZARRAY)
9590 /* See the examples in Partition VI, Annex B */
9591 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9597 #ifndef DISABLE_REFLECTION_EMIT
9599 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9602 /* Preallocate a large enough buffer */
9603 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9604 char *str = type_get_qualified_name (type, NULL);
9607 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9608 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9614 len += strlen (name);
9616 if ((p-buffer) + 20 + len >= *buflen) {
9620 newbuf = g_realloc (buffer, *buflen);
9621 p = newbuf + (p-buffer);
9625 encode_field_or_prop_type (type, p, &p);
9627 len = strlen (name);
9628 mono_metadata_encode_value (len, p, &p);
9629 memcpy (p, name, len);
9631 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9633 *retbuffer = buffer;
9637 * mono_reflection_get_custom_attrs_blob:
9638 * @ctor: custom attribute constructor
9639 * @ctorArgs: arguments o the constructor
9645 * Creates the blob of data that needs to be saved in the metadata and that represents
9646 * the custom attributed described by @ctor, @ctorArgs etc.
9647 * Returns: a Byte array representing the blob of data.
9650 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9653 MonoMethodSignature *sig;
9658 MONO_ARCH_SAVE_REGS;
9660 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9661 /* sig is freed later so allocate it in the heap */
9662 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9664 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9667 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9669 p = buffer = g_malloc (buflen);
9670 /* write the prolog */
9673 for (i = 0; i < sig->param_count; ++i) {
9674 arg = mono_array_get (ctorArgs, MonoObject*, i);
9675 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9679 i += mono_array_length (properties);
9681 i += mono_array_length (fields);
9683 *p++ = (i >> 8) & 0xff;
9686 for (i = 0; i < mono_array_length (properties); ++i) {
9690 prop = mono_array_get (properties, gpointer, i);
9691 get_prop_name_and_type (prop, &pname, &ptype);
9692 *p++ = 0x54; /* PROPERTY signature */
9693 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9700 for (i = 0; i < mono_array_length (fields); ++i) {
9704 field = mono_array_get (fields, gpointer, i);
9705 get_field_name_and_type (field, &fname, &ftype);
9706 *p++ = 0x53; /* FIELD signature */
9707 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9712 g_assert (p - buffer <= buflen);
9713 buflen = p - buffer;
9714 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9715 p = mono_array_addr (result, char, 0);
9716 memcpy (p, buffer, buflen);
9718 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9724 * mono_reflection_setup_internal_class:
9725 * @tb: a TypeBuilder object
9727 * Creates a MonoClass that represents the TypeBuilder.
9728 * This is a trick that lets us simplify a lot of reflection code
9729 * (and will allow us to support Build and Run assemblies easier).
9732 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9735 MonoClass *klass, *parent;
9737 MONO_ARCH_SAVE_REGS;
9739 RESOLVE_TYPE (tb->parent);
9741 mono_loader_lock ();
9744 /* check so we can compile corlib correctly */
9745 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9746 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9747 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9749 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9755 /* the type has already being created: it means we just have to change the parent */
9756 if (tb->type.type) {
9757 klass = mono_class_from_mono_type (tb->type.type);
9758 klass->parent = NULL;
9759 /* fool mono_class_setup_parent */
9760 klass->supertypes = NULL;
9761 mono_class_setup_parent (klass, parent);
9762 mono_class_setup_mono_type (klass);
9763 mono_loader_unlock ();
9767 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9769 klass->image = &tb->module->dynamic_image->image;
9771 klass->inited = 1; /* we lie to the runtime */
9772 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9773 if (!mono_error_ok (&error))
9775 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9776 if (!mono_error_ok (&error))
9778 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9779 klass->flags = tb->attrs;
9781 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9783 klass->element_class = klass;
9785 if (mono_class_get_ref_info (klass) == NULL) {
9787 mono_class_set_ref_info (klass, tb);
9789 /* Put into cache so mono_class_get () will find it.
9790 Skip nested types as those should not be available on the global scope. */
9791 if (!tb->nesting_type) {
9792 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9794 klass->image->reflection_info_unregister_classes =
9795 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9798 g_assert (mono_class_get_ref_info (klass) == tb);
9801 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9802 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9804 if (parent != NULL) {
9805 mono_class_setup_parent (klass, parent);
9806 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9807 const char *old_n = klass->name;
9808 /* trick to get relative numbering right when compiling corlib */
9809 klass->name = "BuildingObject";
9810 mono_class_setup_parent (klass, mono_defaults.object_class);
9811 klass->name = old_n;
9814 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9815 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9816 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9817 klass->instance_size = sizeof (MonoObject);
9818 klass->size_inited = 1;
9819 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9822 mono_class_setup_mono_type (klass);
9824 mono_class_setup_supertypes (klass);
9827 * FIXME: handle interfaces.
9830 tb->type.type = &klass->byval_arg;
9832 if (tb->nesting_type) {
9833 g_assert (tb->nesting_type->type);
9834 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9837 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9839 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9841 mono_loader_unlock ();
9845 mono_loader_unlock ();
9846 mono_error_raise_exception (&error);
9850 * mono_reflection_setup_generic_class:
9851 * @tb: a TypeBuilder object
9853 * Setup the generic class before adding the first generic parameter.
9856 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9861 * mono_reflection_create_generic_class:
9862 * @tb: a TypeBuilder object
9864 * Creates the generic class after all generic parameters have been added.
9867 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9872 MONO_ARCH_SAVE_REGS;
9874 klass = mono_class_from_mono_type (tb->type.type);
9876 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9878 if (klass->generic_container || (count == 0))
9881 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9883 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9885 klass->generic_container->owner.klass = klass;
9886 klass->generic_container->type_argc = count;
9887 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9889 klass->is_generic = 1;
9891 for (i = 0; i < count; i++) {
9892 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9893 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9894 klass->generic_container->type_params [i] = *param;
9895 /*Make sure we are a diferent type instance */
9896 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9897 klass->generic_container->type_params [i].info.pklass = NULL;
9898 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9900 g_assert (klass->generic_container->type_params [i].param.owner);
9903 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9907 * mono_reflection_create_internal_class:
9908 * @tb: a TypeBuilder object
9910 * Actually create the MonoClass that is associated with the TypeBuilder.
9913 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9917 MONO_ARCH_SAVE_REGS;
9919 klass = mono_class_from_mono_type (tb->type.type);
9921 mono_loader_lock ();
9922 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9923 MonoReflectionFieldBuilder *fb;
9925 MonoType *enum_basetype;
9927 g_assert (tb->fields != NULL);
9928 g_assert (mono_array_length (tb->fields) >= 1);
9930 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9932 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9933 mono_loader_unlock ();
9937 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9938 klass->element_class = mono_class_from_mono_type (enum_basetype);
9939 if (!klass->element_class)
9940 klass->element_class = mono_class_from_mono_type (enum_basetype);
9943 * get the element_class from the current corlib.
9945 ec = default_class_from_mono_type (enum_basetype);
9946 klass->instance_size = ec->instance_size;
9947 klass->size_inited = 1;
9949 * this is almost safe to do with enums and it's needed to be able
9950 * to create objects of the enum type (for use in SetConstant).
9952 /* FIXME: Does this mean enums can't have method overrides ? */
9953 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9955 mono_loader_unlock ();
9958 static MonoMarshalSpec*
9959 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9960 MonoReflectionMarshal *minfo)
9962 MonoMarshalSpec *res;
9964 res = image_g_new0 (image, MonoMarshalSpec, 1);
9965 res->native = minfo->type;
9967 switch (minfo->type) {
9968 case MONO_NATIVE_LPARRAY:
9969 res->data.array_data.elem_type = minfo->eltype;
9970 if (minfo->has_size) {
9971 res->data.array_data.param_num = minfo->param_num;
9972 res->data.array_data.num_elem = minfo->count;
9973 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9976 res->data.array_data.param_num = -1;
9977 res->data.array_data.num_elem = -1;
9978 res->data.array_data.elem_mult = -1;
9982 case MONO_NATIVE_BYVALTSTR:
9983 case MONO_NATIVE_BYVALARRAY:
9984 res->data.array_data.num_elem = minfo->count;
9987 case MONO_NATIVE_CUSTOM:
9988 if (minfo->marshaltyperef)
9989 res->data.custom_data.custom_name =
9990 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9992 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10001 #endif /* !DISABLE_REFLECTION_EMIT */
10003 MonoReflectionMarshal*
10004 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10005 MonoMarshalSpec *spec)
10007 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10008 MonoReflectionMarshal *minfo;
10011 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10012 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10013 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10014 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10017 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10018 minfo->type = spec->native;
10020 switch (minfo->type) {
10021 case MONO_NATIVE_LPARRAY:
10022 minfo->eltype = spec->data.array_data.elem_type;
10023 minfo->count = spec->data.array_data.num_elem;
10024 minfo->param_num = spec->data.array_data.param_num;
10027 case MONO_NATIVE_BYVALTSTR:
10028 case MONO_NATIVE_BYVALARRAY:
10029 minfo->count = spec->data.array_data.num_elem;
10032 case MONO_NATIVE_CUSTOM:
10033 if (spec->data.custom_data.custom_name) {
10034 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10036 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10038 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10040 if (spec->data.custom_data.cookie)
10041 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10051 #ifndef DISABLE_REFLECTION_EMIT
10053 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10054 ReflectionMethodBuilder *rmb,
10055 MonoMethodSignature *sig)
10059 MonoMethodWrapper *wrapperm;
10060 MonoMarshalSpec **specs;
10061 MonoReflectionMethodAux *method_aux;
10066 mono_error_init (&error);
10068 * Methods created using a MethodBuilder should have their memory allocated
10069 * inside the image mempool, while dynamic methods should have their memory
10072 dynamic = rmb->refs != NULL;
10073 image = dynamic ? NULL : klass->image;
10076 g_assert (!klass->generic_class);
10078 mono_loader_lock ();
10080 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10081 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10082 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10084 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10086 wrapperm = (MonoMethodWrapper*)m;
10088 m->dynamic = dynamic;
10090 m->flags = rmb->attrs;
10091 m->iflags = rmb->iattrs;
10092 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10094 m->signature = sig;
10095 m->sre_method = TRUE;
10096 m->skip_visibility = rmb->skip_visibility;
10097 if (rmb->table_idx)
10098 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10100 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10101 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10102 m->string_ctor = 1;
10104 m->signature->pinvoke = 1;
10105 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10106 m->signature->pinvoke = 1;
10108 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10110 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10111 g_assert (mono_error_ok (&error));
10112 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10113 g_assert (mono_error_ok (&error));
10115 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10117 if (klass->image->dynamic)
10118 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10120 mono_loader_unlock ();
10123 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10124 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10125 MonoMethodHeader *header;
10127 gint32 max_stack, i;
10128 gint32 num_locals = 0;
10129 gint32 num_clauses = 0;
10133 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10134 code_size = rmb->ilgen->code_len;
10135 max_stack = rmb->ilgen->max_stack;
10136 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10137 if (rmb->ilgen->ex_handlers)
10138 num_clauses = method_count_clauses (rmb->ilgen);
10141 code = mono_array_addr (rmb->code, guint8, 0);
10142 code_size = mono_array_length (rmb->code);
10143 /* we probably need to run a verifier on the code... */
10153 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10154 header->code_size = code_size;
10155 header->code = image_g_malloc (image, code_size);
10156 memcpy ((char*)header->code, code, code_size);
10157 header->max_stack = max_stack;
10158 header->init_locals = rmb->init_locals;
10159 header->num_locals = num_locals;
10161 for (i = 0; i < num_locals; ++i) {
10162 MonoReflectionLocalBuilder *lb =
10163 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10165 header->locals [i] = image_g_new0 (image, MonoType, 1);
10166 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10169 header->num_clauses = num_clauses;
10171 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10172 rmb->ilgen, num_clauses);
10175 wrapperm->header = header;
10178 if (rmb->generic_params) {
10179 int count = mono_array_length (rmb->generic_params);
10180 MonoGenericContainer *container = rmb->generic_container;
10182 g_assert (container);
10184 container->type_argc = count;
10185 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10186 container->owner.method = m;
10188 m->is_generic = TRUE;
10189 mono_method_set_generic_container (m, container);
10191 for (i = 0; i < count; i++) {
10192 MonoReflectionGenericParam *gp =
10193 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10194 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10195 container->type_params [i] = *param;
10199 * The method signature might have pointers to generic parameters that belong to other methods.
10200 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10201 * generic parameters.
10203 for (i = 0; i < m->signature->param_count; ++i) {
10204 MonoType *t = m->signature->params [i];
10205 if (t->type == MONO_TYPE_MVAR) {
10206 MonoGenericParam *gparam = t->data.generic_param;
10207 if (gparam->num < count) {
10208 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10209 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10215 if (klass->generic_container) {
10216 container->parent = klass->generic_container;
10217 container->context.class_inst = klass->generic_container->context.class_inst;
10219 container->context.method_inst = mono_get_shared_generic_inst (container);
10223 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10227 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10229 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10230 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10231 for (i = 0; i < rmb->nrefs; ++i)
10232 data [i + 1] = rmb->refs [i];
10237 /* Parameter info */
10240 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10241 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10242 for (i = 0; i <= m->signature->param_count; ++i) {
10243 MonoReflectionParamBuilder *pb;
10244 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10245 if ((i > 0) && (pb->attrs)) {
10246 /* Make a copy since it might point to a shared type structure */
10247 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10248 m->signature->params [i - 1]->attrs = pb->attrs;
10251 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10252 MonoDynamicImage *assembly;
10253 guint32 idx, def_type, len;
10257 if (!method_aux->param_defaults) {
10258 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10259 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10261 assembly = (MonoDynamicImage*)klass->image;
10262 idx = encode_constant (assembly, pb->def_value, &def_type);
10263 /* Copy the data from the blob since it might get realloc-ed */
10264 p = assembly->blob.data + idx;
10265 len = mono_metadata_decode_blob_size (p, &p2);
10267 method_aux->param_defaults [i] = image_g_malloc (image, len);
10268 method_aux->param_default_types [i] = def_type;
10269 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10273 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10274 g_assert (mono_error_ok (&error));
10277 if (!method_aux->param_cattr)
10278 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10279 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10285 /* Parameter marshalling */
10288 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10289 MonoReflectionParamBuilder *pb;
10290 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10291 if (pb->marshal_info) {
10293 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10294 specs [pb->position] =
10295 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10299 if (specs != NULL) {
10301 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10302 method_aux->param_marshall = specs;
10305 if (klass->image->dynamic && method_aux)
10306 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10308 mono_loader_unlock ();
10314 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10316 ReflectionMethodBuilder rmb;
10317 MonoMethodSignature *sig;
10319 mono_loader_lock ();
10320 sig = ctor_builder_to_signature (klass->image, mb);
10321 mono_loader_unlock ();
10323 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10325 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10326 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10328 /* If we are in a generic class, we might be called multiple times from inflate_method */
10329 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10330 /* ilgen is no longer needed */
10334 return mb->mhandle;
10338 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10340 ReflectionMethodBuilder rmb;
10341 MonoMethodSignature *sig;
10343 mono_loader_lock ();
10344 sig = method_builder_to_signature (klass->image, mb);
10345 mono_loader_unlock ();
10347 reflection_methodbuilder_from_method_builder (&rmb, mb);
10349 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10350 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10352 /* If we are in a generic class, we might be called multiple times from inflate_method */
10353 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10354 /* ilgen is no longer needed */
10357 return mb->mhandle;
10360 static MonoClassField*
10361 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10363 MonoClassField *field;
10367 field = g_new0 (MonoClassField, 1);
10369 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10370 g_assert (mono_error_ok (&error));
10371 if (fb->attrs || fb->modreq || fb->modopt) {
10372 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10373 field->type->attrs = fb->attrs;
10375 g_assert (klass->image->dynamic);
10376 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10377 g_free (field->type);
10378 field->type = mono_metadata_type_dup (klass->image, custom);
10381 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10383 if (fb->offset != -1)
10384 field->offset = fb->offset;
10385 field->parent = klass;
10386 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10388 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10395 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10398 MonoReflectionTypeBuilder *tb = NULL;
10399 gboolean is_dynamic = FALSE;
10400 MonoDomain *domain;
10401 MonoClass *geninst;
10403 mono_loader_lock ();
10405 domain = mono_object_domain (type);
10407 if (is_sre_type_builder (mono_object_class (type))) {
10408 tb = (MonoReflectionTypeBuilder *) type;
10411 } else if (is_sre_generic_instance (mono_object_class (type))) {
10412 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10413 MonoReflectionType *gtd = rgi->generic_type;
10415 if (is_sre_type_builder (mono_object_class (gtd))) {
10416 tb = (MonoReflectionTypeBuilder *)gtd;
10421 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10422 if (tb && tb->generic_container)
10423 mono_reflection_create_generic_class (tb);
10425 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10426 if (!klass->generic_container) {
10427 mono_loader_unlock ();
10431 if (klass->wastypebuilder) {
10432 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10437 mono_loader_unlock ();
10439 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10441 return &geninst->byval_arg;
10445 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10447 MonoGenericClass *gclass;
10448 MonoGenericInst *inst;
10450 g_assert (klass->generic_container);
10452 inst = mono_metadata_get_generic_inst (type_argc, types);
10453 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10455 return mono_generic_class_get_class (gclass);
10458 MonoReflectionMethod*
10459 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10462 MonoMethod *method, *inflated;
10463 MonoMethodInflated *imethod;
10464 MonoGenericContext tmp_context;
10465 MonoGenericInst *ginst;
10466 MonoType **type_argv;
10469 MONO_ARCH_SAVE_REGS;
10471 /*FIXME but this no longer should happen*/
10472 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10473 #ifndef DISABLE_REFLECTION_EMIT
10474 MonoReflectionMethodBuilder *mb = NULL;
10475 MonoReflectionTypeBuilder *tb;
10478 mb = (MonoReflectionMethodBuilder *) rmethod;
10479 tb = (MonoReflectionTypeBuilder *) mb->type;
10480 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10482 method = methodbuilder_to_mono_method (klass, mb);
10484 g_assert_not_reached ();
10488 method = rmethod->method;
10491 klass = method->klass;
10493 if (method->is_inflated)
10494 method = ((MonoMethodInflated *) method)->declaring;
10496 count = mono_method_signature (method)->generic_param_count;
10497 if (count != mono_array_length (types))
10500 type_argv = g_new0 (MonoType *, count);
10501 for (i = 0; i < count; i++) {
10502 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10503 type_argv [i] = mono_reflection_type_get_handle (garg);
10505 ginst = mono_metadata_get_generic_inst (count, type_argv);
10506 g_free (type_argv);
10508 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10509 tmp_context.method_inst = ginst;
10511 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10512 imethod = (MonoMethodInflated *) inflated;
10514 /*FIXME but I think this is no longer necessary*/
10515 if (method->klass->image->dynamic) {
10516 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10518 * This table maps metadata structures representing inflated methods/fields
10519 * to the reflection objects representing their generic definitions.
10521 mono_loader_lock ();
10522 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10523 mono_loader_unlock ();
10526 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10527 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10529 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10532 #ifndef DISABLE_REFLECTION_EMIT
10534 static MonoMethod *
10535 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10537 MonoMethodInflated *imethod;
10538 MonoGenericContext *context;
10542 * With generic code sharing the klass might not be inflated.
10543 * This can happen because classes inflated with their own
10544 * type arguments are "normalized" to the uninflated class.
10546 if (!klass->generic_class)
10549 context = mono_class_get_context (klass);
10551 if (klass->method.count && klass->methods) {
10552 /* Find the already created inflated method */
10553 for (i = 0; i < klass->method.count; ++i) {
10554 g_assert (klass->methods [i]->is_inflated);
10555 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10558 g_assert (i < klass->method.count);
10559 imethod = (MonoMethodInflated*)klass->methods [i];
10561 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10564 if (method->is_generic && method->klass->image->dynamic) {
10565 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10567 mono_loader_lock ();
10568 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10569 mono_loader_unlock ();
10571 return (MonoMethod *) imethod;
10574 static MonoMethod *
10575 inflate_method (MonoReflectionType *type, MonoObject *obj)
10577 MonoMethod *method;
10580 MonoClass *type_class = mono_object_class (type);
10582 if (is_sre_generic_instance (type_class)) {
10583 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10584 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10585 } else if (is_sre_type_builder (type_class)) {
10586 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10587 } else if (type->type) {
10588 gklass = mono_class_from_mono_type (type->type);
10589 gklass = mono_class_get_generic_type_definition (gklass);
10591 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10594 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10595 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10596 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10598 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10599 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10600 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10601 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10602 method = ((MonoReflectionMethod *) obj)->method;
10604 method = NULL; /* prevent compiler warning */
10605 g_error ("can't handle type %s", obj->vtable->klass->name);
10608 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10611 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10613 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10614 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10617 MonoGenericClass *gclass;
10618 MonoDynamicGenericClass *dgclass;
10619 MonoClass *klass, *gklass;
10623 MONO_ARCH_SAVE_REGS;
10625 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10626 klass = mono_class_from_mono_type (gtype);
10627 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10628 gclass = gtype->data.generic_class;
10630 if (!gclass->is_dynamic)
10633 dgclass = (MonoDynamicGenericClass *) gclass;
10635 if (dgclass->initialized)
10638 gklass = gclass->container_class;
10639 mono_class_init (gklass);
10641 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10643 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10644 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10645 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10647 for (i = 0; i < dgclass->count_fields; i++) {
10648 MonoObject *obj = mono_array_get (fields, gpointer, i);
10649 MonoClassField *field, *inflated_field = NULL;
10651 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10652 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10653 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10654 field = ((MonoReflectionField *) obj)->field;
10656 field = NULL; /* prevent compiler warning */
10657 g_assert_not_reached ();
10660 dgclass->fields [i] = *field;
10661 dgclass->fields [i].parent = klass;
10662 dgclass->fields [i].type = mono_class_inflate_generic_type (
10663 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10664 dgclass->field_generic_types [i] = field->type;
10665 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10666 dgclass->field_objects [i] = obj;
10668 if (inflated_field) {
10669 g_free (inflated_field);
10671 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10675 dgclass->initialized = TRUE;
10679 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10681 MonoDynamicGenericClass *dgclass;
10684 g_assert (gclass->is_dynamic);
10686 dgclass = (MonoDynamicGenericClass *)gclass;
10688 for (i = 0; i < dgclass->count_fields; ++i) {
10689 MonoClassField *field = dgclass->fields + i;
10690 mono_metadata_free_type (field->type);
10691 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10696 fix_partial_generic_class (MonoClass *klass)
10698 MonoClass *gklass = klass->generic_class->container_class;
10699 MonoDynamicGenericClass *dgclass;
10702 if (klass->wastypebuilder)
10705 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10706 if (klass->parent != gklass->parent) {
10708 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10709 if (mono_error_ok (&error)) {
10710 MonoClass *parent = mono_class_from_mono_type (parent_type);
10711 mono_metadata_free_type (parent_type);
10712 if (parent != klass->parent) {
10713 /*fool mono_class_setup_parent*/
10714 klass->supertypes = NULL;
10715 mono_class_setup_parent (klass, parent);
10718 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10719 mono_error_cleanup (&error);
10720 if (gklass->wastypebuilder)
10721 klass->wastypebuilder = TRUE;
10726 if (!dgclass->initialized)
10729 if (klass->method.count != gklass->method.count) {
10730 klass->method.count = gklass->method.count;
10731 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10733 for (i = 0; i < klass->method.count; i++) {
10734 klass->methods [i] = mono_class_inflate_generic_method_full (
10735 gklass->methods [i], klass, mono_class_get_context (klass));
10739 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10740 klass->interface_count = gklass->interface_count;
10741 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10742 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10744 for (i = 0; i < gklass->interface_count; ++i) {
10745 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10746 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10747 mono_metadata_free_type (iface_type);
10749 ensure_runtime_vtable (klass->interfaces [i]);
10751 klass->interfaces_inited = 1;
10754 if (klass->field.count != gklass->field.count) {
10755 klass->field.count = gklass->field.count;
10756 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10758 for (i = 0; i < klass->field.count; i++) {
10759 klass->fields [i] = gklass->fields [i];
10760 klass->fields [i].parent = klass;
10761 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10765 /*We can only finish with this klass once it's parent has as well*/
10766 if (gklass->wastypebuilder)
10767 klass->wastypebuilder = TRUE;
10772 ensure_generic_class_runtime_vtable (MonoClass *klass)
10774 MonoClass *gklass = klass->generic_class->container_class;
10776 ensure_runtime_vtable (gklass);
10778 fix_partial_generic_class (klass);
10782 ensure_runtime_vtable (MonoClass *klass)
10784 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10787 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10790 ensure_runtime_vtable (klass->parent);
10793 num = tb->ctors? mono_array_length (tb->ctors): 0;
10794 num += tb->num_methods;
10795 klass->method.count = num;
10796 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10797 num = tb->ctors? mono_array_length (tb->ctors): 0;
10798 for (i = 0; i < num; ++i)
10799 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10800 num = tb->num_methods;
10802 for (i = 0; i < num; ++i)
10803 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10805 if (tb->interfaces) {
10806 klass->interface_count = mono_array_length (tb->interfaces);
10807 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10808 for (i = 0; i < klass->interface_count; ++i) {
10809 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10810 klass->interfaces [i] = mono_class_from_mono_type (iface);
10811 ensure_runtime_vtable (klass->interfaces [i]);
10813 klass->interfaces_inited = 1;
10815 } else if (klass->generic_class){
10816 ensure_generic_class_runtime_vtable (klass);
10819 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10821 for (i = 0; i < klass->method.count; ++i) {
10822 MonoMethod *im = klass->methods [i];
10823 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10824 im->slot = slot_num++;
10827 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10828 mono_class_setup_interface_offsets (klass);
10829 mono_class_setup_interface_id (klass);
10833 * The generic vtable is needed even if image->run is not set since some
10834 * runtime code like ves_icall_Type_GetMethodsByName depends on
10835 * method->slot being defined.
10839 * tb->methods could not be freed since it is used for determining
10840 * overrides during dynamic vtable construction.
10845 mono_reflection_method_get_handle (MonoObject *method)
10847 MonoClass *class = mono_object_class (method);
10848 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10849 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10850 return sr_method->method;
10852 if (is_sre_method_builder (class)) {
10853 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10854 return mb->mhandle;
10856 if (is_sre_method_on_tb_inst (class)) {
10857 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10858 MonoMethod *result;
10859 /*FIXME move this to a proper method and unify with resolve_object*/
10860 if (m->method_args) {
10861 result = mono_reflection_method_on_tb_inst_get_handle (m);
10863 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10864 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10865 MonoMethod *mono_method;
10867 if (is_sre_method_builder (mono_object_class (m->mb)))
10868 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10869 else if (is_sr_mono_method (mono_object_class (m->mb)))
10870 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10872 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
10874 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10879 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10884 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10886 MonoReflectionTypeBuilder *tb;
10890 *num_overrides = 0;
10892 g_assert (klass->image->dynamic);
10894 if (!mono_class_get_ref_info (klass))
10897 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10899 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10903 for (i = 0; i < tb->num_methods; ++i) {
10904 MonoReflectionMethodBuilder *mb =
10905 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10906 if (mb->override_method)
10912 *overrides = g_new0 (MonoMethod*, onum * 2);
10915 for (i = 0; i < tb->num_methods; ++i) {
10916 MonoReflectionMethodBuilder *mb =
10917 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10918 if (mb->override_method) {
10919 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10920 (*overrides) [onum * 2 + 1] = mb->mhandle;
10922 g_assert (mb->mhandle);
10929 *num_overrides = onum;
10933 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10935 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10936 MonoReflectionFieldBuilder *fb;
10937 MonoClassField *field;
10938 MonoImage *image = klass->image;
10939 const char *p, *p2;
10941 guint32 len, idx, real_size = 0;
10943 klass->field.count = tb->num_fields;
10944 klass->field.first = 0;
10946 mono_error_init (error);
10948 if (tb->class_size) {
10949 if ((tb->packing_size & 0xfffffff0) != 0) {
10950 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10951 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10954 klass->packing_size = tb->packing_size;
10955 real_size = klass->instance_size + tb->class_size;
10958 if (!klass->field.count) {
10959 klass->instance_size = MAX (klass->instance_size, real_size);
10963 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10964 mono_class_alloc_ext (klass);
10965 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10967 This is, guess what, a hack.
10968 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10969 On the static path no field class is resolved, only types are built. This is the right thing to do
10971 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10973 klass->size_inited = 1;
10975 for (i = 0; i < klass->field.count; ++i) {
10976 MonoArray *rva_data;
10977 fb = mono_array_get (tb->fields, gpointer, i);
10978 field = &klass->fields [i];
10979 field->name = mono_string_to_utf8_image (image, fb->name, error);
10980 if (!mono_error_ok (error))
10983 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10984 field->type->attrs = fb->attrs;
10986 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10989 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
10990 char *base = mono_array_addr (rva_data, char, 0);
10991 size_t size = mono_array_length (rva_data);
10992 char *data = mono_image_alloc (klass->image, size);
10993 memcpy (data, base, size);
10994 klass->ext->field_def_values [i].data = data;
10996 if (fb->offset != -1)
10997 field->offset = fb->offset;
10998 field->parent = klass;
10999 fb->handle = field;
11000 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11002 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11003 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11005 if (fb->def_value) {
11006 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11007 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11008 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11009 /* Copy the data from the blob since it might get realloc-ed */
11010 p = assembly->blob.data + idx;
11011 len = mono_metadata_decode_blob_size (p, &p2);
11013 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11014 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11018 klass->instance_size = MAX (klass->instance_size, real_size);
11019 mono_class_layout_fields (klass);
11023 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11025 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11026 MonoReflectionPropertyBuilder *pb;
11027 MonoImage *image = klass->image;
11028 MonoProperty *properties;
11031 mono_error_init (error);
11034 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11036 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11037 klass->ext->property.first = 0;
11039 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11040 klass->ext->properties = properties;
11041 for (i = 0; i < klass->ext->property.count; ++i) {
11042 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11043 properties [i].parent = klass;
11044 properties [i].attrs = pb->attrs;
11045 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11046 if (!mono_error_ok (error))
11048 if (pb->get_method)
11049 properties [i].get = pb->get_method->mhandle;
11050 if (pb->set_method)
11051 properties [i].set = pb->set_method->mhandle;
11053 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11054 if (pb->def_value) {
11056 const char *p, *p2;
11057 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11058 if (!klass->ext->prop_def_values)
11059 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11060 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11061 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11062 /* Copy the data from the blob since it might get realloc-ed */
11063 p = assembly->blob.data + idx;
11064 len = mono_metadata_decode_blob_size (p, &p2);
11066 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11067 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11072 MonoReflectionEvent *
11073 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11075 MonoEvent *event = g_new0 (MonoEvent, 1);
11078 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11080 event->parent = klass;
11081 event->attrs = eb->attrs;
11082 event->name = mono_string_to_utf8 (eb->name);
11083 if (eb->add_method)
11084 event->add = eb->add_method->mhandle;
11085 if (eb->remove_method)
11086 event->remove = eb->remove_method->mhandle;
11087 if (eb->raise_method)
11088 event->raise = eb->raise_method->mhandle;
11090 #ifndef MONO_SMALL_CONFIG
11091 if (eb->other_methods) {
11093 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11094 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11095 MonoReflectionMethodBuilder *mb =
11096 mono_array_get (eb->other_methods,
11097 MonoReflectionMethodBuilder*, j);
11098 event->other [j] = mb->mhandle;
11103 return mono_event_get_object (mono_object_domain (tb), klass, event);
11107 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11109 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11110 MonoReflectionEventBuilder *eb;
11111 MonoImage *image = klass->image;
11115 mono_error_init (error);
11118 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11120 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11121 klass->ext->event.first = 0;
11123 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11124 klass->ext->events = events;
11125 for (i = 0; i < klass->ext->event.count; ++i) {
11126 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11127 events [i].parent = klass;
11128 events [i].attrs = eb->attrs;
11129 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11130 if (!mono_error_ok (error))
11132 if (eb->add_method)
11133 events [i].add = eb->add_method->mhandle;
11134 if (eb->remove_method)
11135 events [i].remove = eb->remove_method->mhandle;
11136 if (eb->raise_method)
11137 events [i].raise = eb->raise_method->mhandle;
11139 #ifndef MONO_SMALL_CONFIG
11140 if (eb->other_methods) {
11142 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11143 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11144 MonoReflectionMethodBuilder *mb =
11145 mono_array_get (eb->other_methods,
11146 MonoReflectionMethodBuilder*, j);
11147 events [i].other [j] = mb->mhandle;
11151 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11156 remove_instantiations_of_and_ensure_contents (gpointer key,
11158 gpointer user_data)
11160 MonoType *type = (MonoType*)key;
11161 MonoClass *klass = (MonoClass*)user_data;
11163 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11164 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11171 check_array_for_usertypes (MonoArray *arr)
11178 for (i = 0; i < mono_array_length (arr); ++i)
11179 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11182 MonoReflectionType*
11183 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11187 MonoDomain* domain;
11188 MonoReflectionType* res;
11191 MONO_ARCH_SAVE_REGS;
11193 domain = mono_object_domain (tb);
11194 klass = mono_class_from_mono_type (tb->type.type);
11197 * Check for user defined Type subclasses.
11199 RESOLVE_TYPE (tb->parent);
11200 check_array_for_usertypes (tb->interfaces);
11202 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11203 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11205 RESOLVE_TYPE (fb->type);
11206 check_array_for_usertypes (fb->modreq);
11207 check_array_for_usertypes (fb->modopt);
11208 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11209 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11214 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11215 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11217 RESOLVE_TYPE (mb->rtype);
11218 check_array_for_usertypes (mb->return_modreq);
11219 check_array_for_usertypes (mb->return_modopt);
11220 check_array_for_usertypes (mb->parameters);
11221 if (mb->param_modreq)
11222 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11223 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11224 if (mb->param_modopt)
11225 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11226 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11231 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11232 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11234 check_array_for_usertypes (mb->parameters);
11235 if (mb->param_modreq)
11236 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11237 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11238 if (mb->param_modopt)
11239 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11240 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11245 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11248 * we need to lock the domain because the lock will be taken inside
11249 * So, we need to keep the locking order correct.
11251 mono_loader_lock ();
11252 mono_domain_lock (domain);
11253 if (klass->wastypebuilder) {
11254 mono_domain_unlock (domain);
11255 mono_loader_unlock ();
11256 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11259 * Fields to set in klass:
11260 * the various flags: delegate/unicode/contextbound etc.
11262 klass->flags = tb->attrs;
11263 klass->has_cctor = 1;
11264 klass->has_finalize = 1;
11265 klass->has_finalize_inited = 1;
11267 /* fool mono_class_setup_parent */
11268 klass->supertypes = NULL;
11269 mono_class_setup_parent (klass, klass->parent);
11270 mono_class_setup_mono_type (klass);
11273 if (!((MonoDynamicImage*)klass->image)->run) {
11274 if (klass->generic_container) {
11275 /* FIXME: The code below can't handle generic classes */
11276 klass->wastypebuilder = TRUE;
11277 mono_loader_unlock ();
11278 mono_domain_unlock (domain);
11279 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11284 /* enums are done right away */
11285 if (!klass->enumtype)
11286 ensure_runtime_vtable (klass);
11288 if (tb->subtypes) {
11289 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11290 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11291 mono_class_alloc_ext (klass);
11292 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)));
11296 klass->nested_classes_inited = TRUE;
11298 /* fields and object layout */
11299 if (klass->parent) {
11300 if (!klass->parent->size_inited)
11301 mono_class_init (klass->parent);
11302 klass->instance_size = klass->parent->instance_size;
11303 klass->sizes.class_size = 0;
11304 klass->min_align = klass->parent->min_align;
11305 /* if the type has no fields we won't call the field_setup
11306 * routine which sets up klass->has_references.
11308 klass->has_references |= klass->parent->has_references;
11310 klass->instance_size = sizeof (MonoObject);
11311 klass->min_align = 1;
11314 /* FIXME: handle packing_size and instance_size */
11315 typebuilder_setup_fields (klass, &error);
11316 if (!mono_error_ok (&error))
11318 typebuilder_setup_properties (klass, &error);
11319 if (!mono_error_ok (&error))
11322 typebuilder_setup_events (klass, &error);
11323 if (!mono_error_ok (&error))
11326 klass->wastypebuilder = TRUE;
11329 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11330 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11331 * we want to return normal System.MonoType objects, so clear these out from the cache.
11333 * Together with this we must ensure the contents of all instances to match the created type.
11335 if (domain->type_hash && klass->generic_container)
11336 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11338 mono_domain_unlock (domain);
11339 mono_loader_unlock ();
11341 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11342 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11343 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11346 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11347 g_assert (res != (MonoReflectionType*)tb);
11352 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11353 klass->wastypebuilder = TRUE;
11354 mono_domain_unlock (domain);
11355 mono_loader_unlock ();
11356 mono_error_raise_exception (&error);
11361 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11363 MonoGenericParamFull *param;
11368 MONO_ARCH_SAVE_REGS;
11370 image = &gparam->tbuilder->module->dynamic_image->image;
11372 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11374 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11375 g_assert (mono_error_ok (&error));
11376 param->param.num = gparam->index;
11378 if (gparam->mbuilder) {
11379 if (!gparam->mbuilder->generic_container) {
11380 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11381 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11382 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11383 gparam->mbuilder->generic_container->is_method = TRUE;
11385 * Cannot set owner.method, since the MonoMethod is not created yet.
11386 * Set the image field instead, so type_in_image () works.
11388 gparam->mbuilder->generic_container->image = klass->image;
11390 param->param.owner = gparam->mbuilder->generic_container;
11391 } else if (gparam->tbuilder) {
11392 if (!gparam->tbuilder->generic_container) {
11393 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11394 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11395 gparam->tbuilder->generic_container->owner.klass = klass;
11397 param->param.owner = gparam->tbuilder->generic_container;
11400 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11402 gparam->type.type = &pklass->byval_arg;
11404 mono_class_set_ref_info (pklass, gparam);
11405 mono_image_lock (image);
11406 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11407 mono_image_unlock (image);
11411 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11413 MonoReflectionModuleBuilder *module = sig->module;
11414 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11415 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11420 check_array_for_usertypes (sig->arguments);
11422 sigbuffer_init (&buf, 32);
11424 sigbuffer_add_value (&buf, 0x07);
11425 sigbuffer_add_value (&buf, na);
11426 if (assembly != NULL){
11427 for (i = 0; i < na; ++i) {
11428 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11429 encode_reflection_type (assembly, type, &buf);
11433 buflen = buf.p - buf.buf;
11434 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11435 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11436 sigbuffer_free (&buf);
11442 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11444 MonoDynamicImage *assembly = sig->module->dynamic_image;
11445 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11450 check_array_for_usertypes (sig->arguments);
11452 sigbuffer_init (&buf, 32);
11454 sigbuffer_add_value (&buf, 0x06);
11455 for (i = 0; i < na; ++i) {
11456 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11457 encode_reflection_type (assembly, type, &buf);
11460 buflen = buf.p - buf.buf;
11461 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11462 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11463 sigbuffer_free (&buf);
11469 MonoMethod *handle;
11470 MonoDomain *domain;
11471 } DynamicMethodReleaseData;
11474 * The runtime automatically clean up those after finalization.
11476 static MonoReferenceQueue *dynamic_method_queue;
11479 free_dynamic_method (void *dynamic_method)
11481 DynamicMethodReleaseData *data = dynamic_method;
11483 mono_runtime_free_method (data->domain, data->handle);
11488 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11490 MonoReferenceQueue *queue;
11491 MonoMethod *handle;
11492 DynamicMethodReleaseData *release_data;
11493 ReflectionMethodBuilder rmb;
11494 MonoMethodSignature *sig;
11499 if (mono_runtime_is_shutting_down ())
11500 mono_raise_exception (mono_get_exception_invalid_operation (""));
11502 if (!(queue = dynamic_method_queue)) {
11503 mono_loader_lock ();
11504 if (!(queue = dynamic_method_queue))
11505 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11506 mono_loader_unlock ();
11509 sig = dynamic_method_to_signature (mb);
11511 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11514 * Resolve references.
11517 * Every second entry in the refs array is reserved for storing handle_class,
11518 * which is needed by the ldtoken implementation in the JIT.
11520 rmb.nrefs = mb->nrefs;
11521 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11522 for (i = 0; i < mb->nrefs; i += 2) {
11523 MonoClass *handle_class;
11525 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11527 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11528 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11530 * The referenced DynamicMethod should already be created by the managed
11531 * code, except in the case of circular references. In that case, we store
11532 * method in the refs array, and fix it up later when the referenced
11533 * DynamicMethod is created.
11535 if (method->mhandle) {
11536 ref = method->mhandle;
11538 /* FIXME: GC object stored in unmanaged memory */
11541 /* FIXME: GC object stored in unmanaged memory */
11542 method->referenced_by = g_slist_append (method->referenced_by, mb);
11544 handle_class = mono_defaults.methodhandle_class;
11546 MonoException *ex = NULL;
11547 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11549 ex = mono_get_exception_type_load (NULL, NULL);
11550 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11551 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11555 mono_raise_exception (ex);
11560 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11561 rmb.refs [i + 1] = handle_class;
11564 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11566 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11567 release_data = g_new (DynamicMethodReleaseData, 1);
11568 release_data->handle = handle;
11569 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11570 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11571 g_free (release_data);
11573 /* Fix up refs entries pointing at us */
11574 for (l = mb->referenced_by; l; l = l->next) {
11575 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11576 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11579 g_assert (method->mhandle);
11581 data = (gpointer*)wrapper->method_data;
11582 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11583 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11584 data [i + 1] = mb->mhandle;
11587 g_slist_free (mb->referenced_by);
11591 /* ilgen is no longer needed */
11595 #endif /* DISABLE_REFLECTION_EMIT */
11599 * mono_reflection_is_valid_dynamic_token:
11601 * Returns TRUE if token is valid.
11605 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11607 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11610 MonoMethodSignature *
11611 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11613 MonoMethodSignature *sig;
11614 g_assert (image->dynamic);
11616 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11620 return mono_method_signature (method);
11623 #ifndef DISABLE_REFLECTION_EMIT
11626 * mono_reflection_lookup_dynamic_token:
11628 * Finish the Builder object pointed to by TOKEN and return the corresponding
11629 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11630 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11633 * LOCKING: Take the loader lock
11636 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11638 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11642 mono_loader_lock ();
11643 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11644 mono_loader_unlock ();
11647 g_error ("Could not find required dynamic token 0x%08x", token);
11653 handle_class = &klass;
11654 return resolve_object (image, obj, handle_class, context);
11658 * ensure_complete_type:
11660 * Ensure that KLASS is completed if it is a dynamic type, or references
11664 ensure_complete_type (MonoClass *klass)
11666 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11667 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11669 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11671 // Asserting here could break a lot of code
11672 //g_assert (klass->wastypebuilder);
11675 if (klass->generic_class) {
11676 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11679 for (i = 0; i < inst->type_argc; ++i) {
11680 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11686 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11688 gpointer result = NULL;
11690 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11691 result = mono_string_intern ((MonoString*)obj);
11692 *handle_class = mono_defaults.string_class;
11694 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11695 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11696 MonoClass *mc = mono_class_from_mono_type (type);
11697 if (!mono_class_init (mc))
11698 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11701 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11702 result = mono_class_from_mono_type (inflated);
11703 mono_metadata_free_type (inflated);
11705 result = mono_class_from_mono_type (type);
11707 *handle_class = mono_defaults.typehandle_class;
11709 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11710 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11711 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11712 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11713 result = ((MonoReflectionMethod*)obj)->method;
11715 result = mono_class_inflate_generic_method (result, context);
11716 *handle_class = mono_defaults.methodhandle_class;
11718 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11719 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11720 result = mb->mhandle;
11722 /* Type is not yet created */
11723 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11725 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11728 * Hopefully this has been filled in by calling CreateType() on the
11732 * TODO: This won't work if the application finishes another
11733 * TypeBuilder instance instead of this one.
11735 result = mb->mhandle;
11738 result = mono_class_inflate_generic_method (result, context);
11739 *handle_class = mono_defaults.methodhandle_class;
11740 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11741 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11743 result = cb->mhandle;
11745 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11747 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11748 result = cb->mhandle;
11751 result = mono_class_inflate_generic_method (result, context);
11752 *handle_class = mono_defaults.methodhandle_class;
11753 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11754 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11756 ensure_complete_type (field->parent);
11758 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11759 MonoClass *class = mono_class_from_mono_type (inflated);
11760 MonoClassField *inflated_field;
11761 gpointer iter = NULL;
11762 mono_metadata_free_type (inflated);
11763 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11764 if (!strcmp (field->name, inflated_field->name))
11767 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11768 result = inflated_field;
11772 *handle_class = mono_defaults.fieldhandle_class;
11774 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11775 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11776 result = fb->handle;
11779 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11781 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11782 result = fb->handle;
11785 if (fb->handle && fb->handle->parent->generic_container) {
11786 MonoClass *klass = fb->handle->parent;
11787 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11788 MonoClass *inflated = mono_class_from_mono_type (type);
11790 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11792 mono_metadata_free_type (type);
11794 *handle_class = mono_defaults.fieldhandle_class;
11795 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11796 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11797 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11800 klass = type->data.klass;
11801 if (klass->wastypebuilder) {
11802 /* Already created */
11806 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11807 result = type->data.klass;
11810 *handle_class = mono_defaults.typehandle_class;
11811 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11812 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11813 MonoMethodSignature *sig;
11816 if (helper->arguments)
11817 nargs = mono_array_length (helper->arguments);
11821 sig = mono_metadata_signature_alloc (image, nargs);
11822 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11823 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11825 if (helper->unmanaged_call_conv) { /* unmanaged */
11826 sig->call_convention = helper->unmanaged_call_conv - 1;
11827 sig->pinvoke = TRUE;
11828 } else if (helper->call_conv & 0x02) {
11829 sig->call_convention = MONO_CALL_VARARG;
11831 sig->call_convention = MONO_CALL_DEFAULT;
11834 sig->param_count = nargs;
11835 /* TODO: Copy type ? */
11836 sig->ret = helper->return_type->type;
11837 for (i = 0; i < nargs; ++i)
11838 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11841 *handle_class = NULL;
11842 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11843 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11844 /* Already created by the managed code */
11845 g_assert (method->mhandle);
11846 result = method->mhandle;
11847 *handle_class = mono_defaults.methodhandle_class;
11848 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11849 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11850 type = mono_class_inflate_generic_type (type, context);
11851 result = mono_class_from_mono_type (type);
11852 *handle_class = mono_defaults.typehandle_class;
11854 mono_metadata_free_type (type);
11855 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11856 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11857 type = mono_class_inflate_generic_type (type, context);
11858 result = mono_class_from_mono_type (type);
11859 *handle_class = mono_defaults.typehandle_class;
11861 mono_metadata_free_type (type);
11862 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11863 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11864 MonoClass *inflated;
11866 MonoClassField *field;
11868 if (is_sre_field_builder (mono_object_class (f->fb)))
11869 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11870 else if (is_sr_mono_field (mono_object_class (f->fb)))
11871 field = ((MonoReflectionField*)f->fb)->field;
11873 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)));
11875 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11876 inflated = mono_class_from_mono_type (type);
11878 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11879 ensure_complete_type (field->parent);
11881 mono_metadata_free_type (type);
11882 *handle_class = mono_defaults.fieldhandle_class;
11883 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11884 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11885 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11886 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11887 MonoMethod *method;
11889 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11890 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11891 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11892 method = ((MonoReflectionMethod *)c->cb)->method;
11894 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)));
11896 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11897 *handle_class = mono_defaults.methodhandle_class;
11898 mono_metadata_free_type (type);
11899 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11900 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11901 if (m->method_args) {
11902 result = mono_reflection_method_on_tb_inst_get_handle (m);
11904 result = mono_class_inflate_generic_method (result, context);
11906 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11907 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11908 MonoMethod *method;
11910 if (is_sre_method_builder (mono_object_class (m->mb)))
11911 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11912 else if (is_sr_mono_method (mono_object_class (m->mb)))
11913 method = ((MonoReflectionMethod *)m->mb)->method;
11915 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)));
11917 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11918 mono_metadata_free_type (type);
11920 *handle_class = mono_defaults.methodhandle_class;
11921 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11922 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11925 MonoMethod *method;
11929 mtype = mono_reflection_type_get_handle (m->parent);
11930 klass = mono_class_from_mono_type (mtype);
11932 /* Find the method */
11934 name = mono_string_to_utf8 (m->name);
11936 while ((method = mono_class_get_methods (klass, &iter))) {
11937 if (!strcmp (method->name, name))
11944 // FIXME: Check parameters/return value etc. match
11947 *handle_class = mono_defaults.methodhandle_class;
11948 } else if (is_sre_array (mono_object_get_class(obj)) ||
11949 is_sre_byref (mono_object_get_class(obj)) ||
11950 is_sre_pointer (mono_object_get_class(obj))) {
11951 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11952 MonoType *type = mono_reflection_type_get_handle (ref_type);
11953 result = mono_class_from_mono_type (type);
11954 *handle_class = mono_defaults.typehandle_class;
11956 g_print ("%s\n", obj->vtable->klass->name);
11957 g_assert_not_reached ();
11962 #else /* DISABLE_REFLECTION_EMIT */
11965 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11967 g_assert_not_reached ();
11972 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11974 g_assert_not_reached ();
11978 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11980 g_assert_not_reached ();
11984 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11986 g_assert_not_reached ();
11990 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11992 g_assert_not_reached ();
11996 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11998 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12002 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12004 g_assert_not_reached ();
12008 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12010 g_assert_not_reached ();
12013 MonoReflectionModule *
12014 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12016 g_assert_not_reached ();
12021 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12023 g_assert_not_reached ();
12028 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12030 g_assert_not_reached ();
12035 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12036 gboolean create_open_instance, gboolean register_token)
12038 g_assert_not_reached ();
12043 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12048 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12049 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12052 g_assert_not_reached ();
12056 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12059 *num_overrides = 0;
12062 MonoReflectionEvent *
12063 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12065 g_assert_not_reached ();
12069 MonoReflectionType*
12070 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12072 g_assert_not_reached ();
12077 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12079 g_assert_not_reached ();
12083 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12085 g_assert_not_reached ();
12090 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12092 g_assert_not_reached ();
12097 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12102 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12108 mono_reflection_type_get_handle (MonoReflectionType* ref)
12116 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12118 g_assert_not_reached ();
12121 #endif /* DISABLE_REFLECTION_EMIT */
12123 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12124 const static guint32 declsec_flags_map[] = {
12125 0x00000000, /* empty */
12126 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12127 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12128 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12129 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12130 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12131 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12132 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12133 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12134 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12135 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12136 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12137 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12138 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12139 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12140 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12141 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12142 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12143 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12147 * Returns flags that includes all available security action associated to the handle.
12148 * @token: metadata token (either for a class or a method)
12149 * @image: image where resides the metadata.
12152 mono_declsec_get_flags (MonoImage *image, guint32 token)
12154 int index = mono_metadata_declsec_from_index (image, token);
12155 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12156 guint32 result = 0;
12160 /* HasSecurity can be present for other, not specially encoded, attributes,
12161 e.g. SuppressUnmanagedCodeSecurityAttribute */
12165 for (i = index; i < t->rows; i++) {
12166 guint32 cols [MONO_DECL_SECURITY_SIZE];
12168 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12169 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12172 action = cols [MONO_DECL_SECURITY_ACTION];
12173 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12174 result |= declsec_flags_map [action];
12176 g_assert_not_reached ();
12183 * Get the security actions (in the form of flags) associated with the specified method.
12185 * @method: The method for which we want the declarative security flags.
12186 * Return the declarative security flags for the method (only).
12188 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12189 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12192 mono_declsec_flags_from_method (MonoMethod *method)
12194 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12195 /* FIXME: No cache (for the moment) */
12196 guint32 idx = mono_method_get_index (method);
12197 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12198 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12199 return mono_declsec_get_flags (method->klass->image, idx);
12205 * Get the security actions (in the form of flags) associated with the specified class.
12207 * @klass: The class for which we want the declarative security flags.
12208 * Return the declarative security flags for the class.
12210 * Note: We cache the flags inside the MonoClass structure as this will get
12211 * called very often (at least for each method).
12214 mono_declsec_flags_from_class (MonoClass *klass)
12216 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12217 if (!klass->ext || !klass->ext->declsec_flags) {
12220 idx = mono_metadata_token_index (klass->type_token);
12221 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12222 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12223 mono_loader_lock ();
12224 mono_class_alloc_ext (klass);
12225 mono_loader_unlock ();
12226 /* we cache the flags on classes */
12227 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12229 return klass->ext->declsec_flags;
12235 * Get the security actions (in the form of flags) associated with the specified assembly.
12237 * @assembly: The assembly for which we want the declarative security flags.
12238 * Return the declarative security flags for the assembly.
12241 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12243 guint32 idx = 1; /* there is only one assembly */
12244 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12245 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12246 return mono_declsec_get_flags (assembly->image, idx);
12251 * Fill actions for the specific index (which may either be an encoded class token or
12252 * an encoded method token) from the metadata image.
12253 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12256 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12257 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12259 MonoBoolean result = FALSE;
12261 guint32 cols [MONO_DECL_SECURITY_SIZE];
12262 int index = mono_metadata_declsec_from_index (image, token);
12265 t = &image->tables [MONO_TABLE_DECLSECURITY];
12266 for (i = index; i < t->rows; i++) {
12267 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12269 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12272 /* if present only replace (class) permissions with method permissions */
12273 /* if empty accept either class or method permissions */
12274 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12275 if (!actions->demand.blob) {
12276 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12277 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12278 actions->demand.blob = (char*) (blob + 2);
12279 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12282 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12283 if (!actions->noncasdemand.blob) {
12284 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12285 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12286 actions->noncasdemand.blob = (char*) (blob + 2);
12287 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12290 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12291 if (!actions->demandchoice.blob) {
12292 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12293 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12294 actions->demandchoice.blob = (char*) (blob + 2);
12295 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12305 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12306 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12308 guint32 idx = mono_metadata_token_index (klass->type_token);
12309 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12310 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12311 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12315 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12316 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12318 guint32 idx = mono_method_get_index (method);
12319 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12320 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12321 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12325 * Collect all actions (that requires to generate code in mini) assigned for
12326 * the specified method.
12327 * Note: Don't use the content of actions if the function return FALSE.
12330 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12332 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12333 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12334 MonoBoolean result = FALSE;
12337 /* quick exit if no declarative security is present in the metadata */
12338 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12341 /* we want the original as the wrapper is "free" of the security informations */
12342 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12343 method = mono_marshal_method_from_wrapper (method);
12348 /* First we look for method-level attributes */
12349 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12350 mono_class_init (method->klass);
12351 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12353 result = mono_declsec_get_method_demands_params (method, demands,
12354 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12357 /* Here we use (or create) the class declarative cache to look for demands */
12358 flags = mono_declsec_flags_from_class (method->klass);
12359 if (flags & mask) {
12361 mono_class_init (method->klass);
12362 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12364 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12365 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12368 /* The boolean return value is used as a shortcut in case nothing needs to
12369 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12375 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12377 * Note: Don't use the content of actions if the function return FALSE.
12380 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12382 MonoBoolean result = FALSE;
12385 /* quick exit if no declarative security is present in the metadata */
12386 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12389 /* we want the original as the wrapper is "free" of the security informations */
12390 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12391 method = mono_marshal_method_from_wrapper (method);
12396 /* results are independant - zeroize both */
12397 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12398 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12400 /* First we look for method-level attributes */
12401 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12402 mono_class_init (method->klass);
12404 result = mono_declsec_get_method_demands_params (method, cmethod,
12405 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12408 /* Here we use (or create) the class declarative cache to look for demands */
12409 flags = mono_declsec_flags_from_class (method->klass);
12410 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12411 mono_class_init (method->klass);
12413 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12414 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12421 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12423 * @klass The inherited class - this is the class that provides the security check (attributes)
12425 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12427 * Note: Don't use the content of actions if the function return FALSE.
12430 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12432 MonoBoolean result = FALSE;
12435 /* quick exit if no declarative security is present in the metadata */
12436 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12439 /* Here we use (or create) the class declarative cache to look for demands */
12440 flags = mono_declsec_flags_from_class (klass);
12441 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12442 mono_class_init (klass);
12443 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12445 result |= mono_declsec_get_class_demands_params (klass, demands,
12446 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12453 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12455 * Note: Don't use the content of actions if the function return FALSE.
12458 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12460 /* quick exit if no declarative security is present in the metadata */
12461 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12464 /* we want the original as the wrapper is "free" of the security informations */
12465 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12466 method = mono_marshal_method_from_wrapper (method);
12471 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12472 mono_class_init (method->klass);
12473 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12475 return mono_declsec_get_method_demands_params (method, demands,
12476 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12483 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12485 guint32 cols [MONO_DECL_SECURITY_SIZE];
12489 int index = mono_metadata_declsec_from_index (image, token);
12493 t = &image->tables [MONO_TABLE_DECLSECURITY];
12494 for (i = index; i < t->rows; i++) {
12495 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12497 /* shortcut - index are ordered */
12498 if (token != cols [MONO_DECL_SECURITY_PARENT])
12501 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12502 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12503 entry->blob = (char*) (metadata + 2);
12504 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12513 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12515 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12516 guint32 idx = mono_method_get_index (method);
12517 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12518 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12519 return get_declsec_action (method->klass->image, idx, action, entry);
12525 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12528 guint32 flags = mono_declsec_flags_from_class (klass);
12529 if (declsec_flags_map [action] & flags) {
12530 guint32 idx = mono_metadata_token_index (klass->type_token);
12531 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12532 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12533 return get_declsec_action (klass->image, idx, action, entry);
12539 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12541 guint32 idx = 1; /* there is only one assembly */
12542 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12543 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12545 return get_declsec_action (assembly->image, idx, action, entry);
12549 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12551 MonoObject *res, *exc;
12553 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12554 static MonoMethod *method = NULL;
12556 if (!System_Reflection_Emit_TypeBuilder) {
12557 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12558 g_assert (System_Reflection_Emit_TypeBuilder);
12560 if (method == NULL) {
12561 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12566 * The result of mono_type_get_object () might be a System.MonoType but we
12567 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12569 g_assert (mono_class_get_ref_info (klass));
12570 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12572 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12574 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12578 return *(MonoBoolean*)mono_object_unbox (res);
12582 * mono_reflection_type_get_type:
12583 * @reftype: the System.Type object
12585 * Returns the MonoType* associated with the C# System.Type object @reftype.
12588 mono_reflection_type_get_type (MonoReflectionType *reftype)
12590 g_assert (reftype);
12592 return mono_reflection_type_get_handle (reftype);