2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
174 static gboolean is_sre_array (MonoClass *class);
175 static gboolean is_sre_byref (MonoClass *class);
176 static gboolean is_sre_pointer (MonoClass *class);
177 static gboolean is_sre_type_builder (MonoClass *class);
178 static gboolean is_sre_method_builder (MonoClass *class);
179 static gboolean is_sre_ctor_builder (MonoClass *class);
180 static gboolean is_sre_field_builder (MonoClass *class);
181 static gboolean is_sr_mono_method (MonoClass *class);
182 static gboolean is_sr_mono_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_generic_method (MonoClass *class);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
185 static gboolean is_sr_mono_field (MonoClass *class);
186 static gboolean is_sr_mono_property (MonoClass *class);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
199 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
200 __type = mono_reflection_type_resolve_user_types (__type); \
201 mono_array_set (arr, MonoReflectionType*, index, __type); \
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220 mono_reflection_init (void)
225 dynamic_image_lock (MonoDynamicImage *image)
228 mono_image_lock ((MonoImage*)image);
229 MONO_FINISH_TRY_BLOCKING;
233 dynamic_image_unlock (MonoDynamicImage *image)
235 mono_image_unlock ((MonoImage*)image);
239 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
241 MONO_REQ_GC_UNSAFE_MODE;
243 dynamic_image_lock (assembly);
244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
245 dynamic_image_unlock (assembly);
249 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
251 MONO_REQ_GC_UNSAFE_MODE;
255 dynamic_image_lock (assembly);
256 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
257 dynamic_image_unlock (assembly);
263 sigbuffer_init (SigBuffer *buf, int size)
265 MONO_REQ_GC_NEUTRAL_MODE;
267 buf->buf = g_malloc (size);
269 buf->end = buf->buf + size;
273 sigbuffer_make_room (SigBuffer *buf, int size)
275 MONO_REQ_GC_NEUTRAL_MODE;
277 if (buf->end - buf->p < size) {
278 int new_size = buf->end - buf->buf + size + 32;
279 char *p = g_realloc (buf->buf, new_size);
280 size = buf->p - buf->buf;
283 buf->end = buf->buf + new_size;
288 sigbuffer_add_value (SigBuffer *buf, guint32 val)
290 MONO_REQ_GC_NEUTRAL_MODE;
292 sigbuffer_make_room (buf, 6);
293 mono_metadata_encode_value (val, buf->p, &buf->p);
297 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
299 MONO_REQ_GC_NEUTRAL_MODE;
301 sigbuffer_make_room (buf, 1);
307 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
309 MONO_REQ_GC_NEUTRAL_MODE;
311 sigbuffer_make_room (buf, size);
312 memcpy (buf->p, p, size);
317 sigbuffer_free (SigBuffer *buf)
319 MONO_REQ_GC_NEUTRAL_MODE;
324 #ifndef DISABLE_REFLECTION_EMIT
328 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
332 image_g_malloc (MonoImage *image, guint size)
334 MONO_REQ_GC_NEUTRAL_MODE;
337 return mono_image_alloc (image, size);
339 return g_malloc (size);
341 #endif /* !DISABLE_REFLECTION_EMIT */
346 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
350 image_g_malloc0 (MonoImage *image, guint size)
352 MONO_REQ_GC_NEUTRAL_MODE;
355 return mono_image_alloc0 (image, size);
357 return g_malloc0 (size);
360 #ifndef DISABLE_REFLECTION_EMIT
362 image_strdup (MonoImage *image, const char *s)
364 MONO_REQ_GC_NEUTRAL_MODE;
367 return mono_image_strdup (image, s);
373 #define image_g_new(image,struct_type, n_structs) \
374 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
376 #define image_g_new0(image,struct_type, n_structs) \
377 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
381 alloc_table (MonoDynamicTable *table, guint nrows)
383 MONO_REQ_GC_NEUTRAL_MODE;
386 g_assert (table->columns);
387 if (nrows + 1 >= table->alloc_rows) {
388 while (nrows + 1 >= table->alloc_rows) {
389 if (table->alloc_rows == 0)
390 table->alloc_rows = 16;
392 table->alloc_rows *= 2;
395 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
400 make_room_in_stream (MonoDynamicStream *stream, int size)
402 MONO_REQ_GC_NEUTRAL_MODE;
404 if (size <= stream->alloc_size)
407 while (stream->alloc_size <= size) {
408 if (stream->alloc_size < 4096)
409 stream->alloc_size = 4096;
411 stream->alloc_size *= 2;
414 stream->data = g_realloc (stream->data, stream->alloc_size);
418 string_heap_insert (MonoDynamicStream *sh, const char *str)
420 MONO_REQ_GC_NEUTRAL_MODE;
424 gpointer oldkey, oldval;
426 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
427 return GPOINTER_TO_UINT (oldval);
429 len = strlen (str) + 1;
432 make_room_in_stream (sh, idx + len);
435 * We strdup the string even if we already copy them in sh->data
436 * so that the string pointers in the hash remain valid even if
437 * we need to realloc sh->data. We may want to avoid that later.
439 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
440 memcpy (sh->data + idx, str, len);
446 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
448 MONO_REQ_GC_UNSAFE_MODE;
450 char *name = mono_string_to_utf8 (str);
452 idx = string_heap_insert (sh, name);
457 #ifndef DISABLE_REFLECTION_EMIT
459 string_heap_init (MonoDynamicStream *sh)
461 MONO_REQ_GC_NEUTRAL_MODE;
464 sh->alloc_size = 4096;
465 sh->data = g_malloc (4096);
466 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
467 string_heap_insert (sh, "");
472 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
474 MONO_REQ_GC_NEUTRAL_MODE;
478 make_room_in_stream (stream, stream->index + len);
479 memcpy (stream->data + stream->index, data, len);
481 stream->index += len;
483 * align index? Not without adding an additional param that controls it since
484 * we may store a blob value in pieces.
490 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
492 MONO_REQ_GC_NEUTRAL_MODE;
496 make_room_in_stream (stream, stream->index + len);
497 memset (stream->data + stream->index, 0, len);
499 stream->index += len;
504 stream_data_align (MonoDynamicStream *stream)
506 MONO_REQ_GC_NEUTRAL_MODE;
509 guint32 count = stream->index % 4;
511 /* we assume the stream data will be aligned */
513 mono_image_add_stream_data (stream, buf, 4 - count);
516 #ifndef DISABLE_REFLECTION_EMIT
518 mono_blob_entry_hash (const char* str)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 len = mono_metadata_decode_blob_size (str, &str);
528 for (str += 1; str < end; str++)
529 h = (h << 5) - h + *str;
537 mono_blob_entry_equal (const char *str1, const char *str2) {
538 MONO_REQ_GC_NEUTRAL_MODE;
543 len = mono_metadata_decode_blob_size (str1, &end1);
544 len2 = mono_metadata_decode_blob_size (str2, &end2);
547 return memcmp (end1, end2, len) == 0;
551 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
553 MONO_REQ_GC_NEUTRAL_MODE;
557 gpointer oldkey, oldval;
559 copy = g_malloc (s1+s2);
560 memcpy (copy, b1, s1);
561 memcpy (copy + s1, b2, s2);
562 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
564 idx = GPOINTER_TO_UINT (oldval);
566 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
567 mono_image_add_stream_data (&assembly->blob, b2, s2);
568 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
574 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
576 MONO_REQ_GC_NEUTRAL_MODE;
580 guint32 size = buf->p - buf->buf;
582 g_assert (size <= (buf->end - buf->buf));
583 mono_metadata_encode_value (size, b, &b);
584 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
588 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
589 * dest may be misaligned.
592 swap_with_size (char *dest, const char* val, int len, int nelem) {
593 MONO_REQ_GC_NEUTRAL_MODE;
594 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
597 for (elem = 0; elem < nelem; ++elem) {
623 g_assert_not_reached ();
629 memcpy (dest, val, len * nelem);
634 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
636 MONO_REQ_GC_UNSAFE_MODE;
640 guint32 idx = 0, len;
642 len = str->length * 2;
643 mono_metadata_encode_value (len, b, &b);
644 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
646 char *swapped = g_malloc (2 * mono_string_length (str));
647 const char *p = (const char*)mono_string_chars (str);
649 swap_with_size (swapped, p, 2, mono_string_length (str));
650 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
654 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
659 #ifndef DISABLE_REFLECTION_EMIT
661 default_class_from_mono_type (MonoType *type)
663 MONO_REQ_GC_NEUTRAL_MODE;
665 switch (type->type) {
666 case MONO_TYPE_OBJECT:
667 return mono_defaults.object_class;
669 return mono_defaults.void_class;
670 case MONO_TYPE_BOOLEAN:
671 return mono_defaults.boolean_class;
673 return mono_defaults.char_class;
675 return mono_defaults.sbyte_class;
677 return mono_defaults.byte_class;
679 return mono_defaults.int16_class;
681 return mono_defaults.uint16_class;
683 return mono_defaults.int32_class;
685 return mono_defaults.uint32_class;
687 return mono_defaults.int_class;
689 return mono_defaults.uint_class;
691 return mono_defaults.int64_class;
693 return mono_defaults.uint64_class;
695 return mono_defaults.single_class;
697 return mono_defaults.double_class;
698 case MONO_TYPE_STRING:
699 return mono_defaults.string_class;
701 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
702 g_assert_not_reached ();
710 * mono_class_get_ref_info:
712 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
715 mono_class_get_ref_info (MonoClass *klass)
717 MONO_REQ_GC_UNSAFE_MODE;
719 if (klass->ref_info_handle == 0)
722 return mono_gchandle_get_target (klass->ref_info_handle);
726 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
728 MONO_REQ_GC_UNSAFE_MODE;
730 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
731 g_assert (klass->ref_info_handle != 0);
735 mono_class_free_ref_info (MonoClass *klass)
737 MONO_REQ_GC_NEUTRAL_MODE;
739 if (klass->ref_info_handle) {
740 mono_gchandle_free (klass->ref_info_handle);
741 klass->ref_info_handle = 0;
746 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
748 MONO_REQ_GC_NEUTRAL_MODE;
751 MonoGenericInst *class_inst;
756 class_inst = gclass->context.class_inst;
758 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
759 klass = gclass->container_class;
760 sigbuffer_add_value (buf, klass->byval_arg.type);
761 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
763 sigbuffer_add_value (buf, class_inst->type_argc);
764 for (i = 0; i < class_inst->type_argc; ++i)
765 encode_type (assembly, class_inst->type_argv [i], buf);
770 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
772 MONO_REQ_GC_NEUTRAL_MODE;
775 g_assert_not_reached ();
780 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
784 case MONO_TYPE_BOOLEAN:
798 case MONO_TYPE_STRING:
799 case MONO_TYPE_OBJECT:
800 case MONO_TYPE_TYPEDBYREF:
801 sigbuffer_add_value (buf, type->type);
804 sigbuffer_add_value (buf, type->type);
805 encode_type (assembly, type->data.type, buf);
807 case MONO_TYPE_SZARRAY:
808 sigbuffer_add_value (buf, type->type);
809 encode_type (assembly, &type->data.klass->byval_arg, buf);
811 case MONO_TYPE_VALUETYPE:
812 case MONO_TYPE_CLASS: {
813 MonoClass *k = mono_class_from_mono_type (type);
815 if (k->generic_container) {
816 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
817 encode_generic_class (assembly, gclass, buf);
820 * Make sure we use the correct type.
822 sigbuffer_add_value (buf, k->byval_arg.type);
824 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
825 * otherwise two typerefs could point to the same type, leading to
826 * verification errors.
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
832 case MONO_TYPE_ARRAY:
833 sigbuffer_add_value (buf, type->type);
834 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
835 sigbuffer_add_value (buf, type->data.array->rank);
836 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
837 sigbuffer_add_value (buf, 0);
839 case MONO_TYPE_GENERICINST:
840 encode_generic_class (assembly, type->data.generic_class, buf);
844 sigbuffer_add_value (buf, type->type);
845 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
848 g_error ("need to encode type %x", type->type);
853 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
855 MONO_REQ_GC_UNSAFE_MODE;
858 sigbuffer_add_value (buf, MONO_TYPE_VOID);
862 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
866 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
868 MONO_REQ_GC_UNSAFE_MODE;
873 for (i = 0; i < mono_array_length (modreq); ++i) {
874 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
875 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
876 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
880 for (i = 0; i < mono_array_length (modopt); ++i) {
881 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
882 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
883 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
888 #ifndef DISABLE_REFLECTION_EMIT
890 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
892 MONO_REQ_GC_UNSAFE_MODE;
896 guint32 nparams = sig->param_count;
902 sigbuffer_init (&buf, 32);
904 * FIXME: vararg, explicit_this, differenc call_conv values...
906 idx = sig->call_convention;
908 idx |= 0x20; /* hasthis */
909 if (sig->generic_param_count)
910 idx |= 0x10; /* generic */
911 sigbuffer_add_byte (&buf, idx);
912 if (sig->generic_param_count)
913 sigbuffer_add_value (&buf, sig->generic_param_count);
914 sigbuffer_add_value (&buf, nparams);
915 encode_type (assembly, sig->ret, &buf);
916 for (i = 0; i < nparams; ++i) {
917 if (i == sig->sentinelpos)
918 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
919 encode_type (assembly, sig->params [i], &buf);
921 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
922 sigbuffer_free (&buf);
928 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
930 MONO_REQ_GC_UNSAFE_MODE;
933 * FIXME: reuse code from method_encode_signature().
937 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
938 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
939 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
942 sigbuffer_init (&buf, 32);
943 /* LAMESPEC: all the call conv spec is foobared */
944 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
945 if (mb->call_conv & 2)
946 idx |= 0x5; /* vararg */
947 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
948 idx |= 0x20; /* hasthis */
950 idx |= 0x10; /* generic */
951 sigbuffer_add_byte (&buf, idx);
953 sigbuffer_add_value (&buf, ngparams);
954 sigbuffer_add_value (&buf, nparams + notypes);
955 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
956 encode_reflection_type (assembly, mb->rtype, &buf);
957 for (i = 0; i < nparams; ++i) {
958 MonoArray *modreq = NULL;
959 MonoArray *modopt = NULL;
960 MonoReflectionType *pt;
962 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
963 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
964 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
965 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
966 encode_custom_modifiers (assembly, modreq, modopt, &buf);
967 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
968 encode_reflection_type (assembly, pt, &buf);
971 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
972 for (i = 0; i < notypes; ++i) {
973 MonoReflectionType *pt;
975 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
976 encode_reflection_type (assembly, pt, &buf);
979 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
980 sigbuffer_free (&buf);
985 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
987 MONO_REQ_GC_UNSAFE_MODE;
989 MonoDynamicTable *table;
991 guint32 idx, sig_idx;
992 guint nl = mono_array_length (ilgen->locals);
996 sigbuffer_init (&buf, 32);
997 sigbuffer_add_value (&buf, 0x07);
998 sigbuffer_add_value (&buf, nl);
999 for (i = 0; i < nl; ++i) {
1000 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1003 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1005 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1007 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1008 sigbuffer_free (&buf);
1010 if (assembly->standalonesig_cache == NULL)
1011 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1012 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1016 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1017 idx = table->next_idx ++;
1019 alloc_table (table, table->rows);
1020 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1022 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1024 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1030 method_count_clauses (MonoReflectionILGen *ilgen)
1032 MONO_REQ_GC_UNSAFE_MODE;
1034 guint32 num_clauses = 0;
1037 MonoILExceptionInfo *ex_info;
1038 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1039 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1040 if (ex_info->handlers)
1041 num_clauses += mono_array_length (ex_info->handlers);
1049 #ifndef DISABLE_REFLECTION_EMIT
1050 static MonoExceptionClause*
1051 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1053 MONO_REQ_GC_UNSAFE_MODE;
1055 MonoExceptionClause *clauses;
1056 MonoExceptionClause *clause;
1057 MonoILExceptionInfo *ex_info;
1058 MonoILExceptionBlock *ex_block;
1059 guint32 finally_start;
1060 int i, j, clause_index;;
1062 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1065 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1066 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1067 finally_start = ex_info->start + ex_info->len;
1068 if (!ex_info->handlers)
1070 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1071 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1072 clause = &(clauses [clause_index]);
1074 clause->flags = ex_block->type;
1075 clause->try_offset = ex_info->start;
1077 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1078 clause->try_len = finally_start - ex_info->start;
1080 clause->try_len = ex_info->len;
1081 clause->handler_offset = ex_block->start;
1082 clause->handler_len = ex_block->len;
1083 if (ex_block->extype) {
1084 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1086 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1087 clause->data.filter_offset = ex_block->filter_offset;
1089 clause->data.filter_offset = 0;
1091 finally_start = ex_block->start + ex_block->len;
1099 #endif /* !DISABLE_REFLECTION_EMIT */
1102 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1104 MONO_REQ_GC_UNSAFE_MODE;
1109 gint32 max_stack, i;
1110 gint32 num_locals = 0;
1111 gint32 num_exception = 0;
1114 char fat_header [12];
1116 guint16 short_value;
1117 guint32 local_sig = 0;
1118 guint32 header_size = 12;
1121 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1122 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1126 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1128 code = mb->ilgen->code;
1129 code_size = mb->ilgen->code_len;
1130 max_stack = mb->ilgen->max_stack;
1131 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1132 if (mb->ilgen->ex_handlers)
1133 num_exception = method_count_clauses (mb->ilgen);
1137 char *name = mono_string_to_utf8 (mb->name);
1138 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1139 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1142 mono_raise_exception (exception);
1145 code_size = mono_array_length (code);
1146 max_stack = 8; /* we probably need to run a verifier on the code... */
1149 stream_data_align (&assembly->code);
1151 /* check for exceptions, maxstack, locals */
1152 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1154 if (code_size < 64 && !(code_size & 1)) {
1155 flags = (code_size << 2) | 0x2;
1156 } else if (code_size < 32 && (code_size & 1)) {
1157 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1161 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1162 /* add to the fixup todo list */
1163 if (mb->ilgen && mb->ilgen->num_token_fixups)
1164 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1165 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1166 return assembly->text_rva + idx;
1170 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1172 * FIXME: need to set also the header size in fat_flags.
1173 * (and more sects and init locals flags)
1177 fat_flags |= METHOD_HEADER_MORE_SECTS;
1178 if (mb->init_locals)
1179 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1180 fat_header [0] = fat_flags;
1181 fat_header [1] = (header_size / 4 ) << 4;
1182 short_value = GUINT16_TO_LE (max_stack);
1183 memcpy (fat_header + 2, &short_value, 2);
1184 int_value = GUINT32_TO_LE (code_size);
1185 memcpy (fat_header + 4, &int_value, 4);
1186 int_value = GUINT32_TO_LE (local_sig);
1187 memcpy (fat_header + 8, &int_value, 4);
1188 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1189 /* add to the fixup todo list */
1190 if (mb->ilgen && mb->ilgen->num_token_fixups)
1191 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1193 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1194 if (num_exception) {
1195 unsigned char sheader [4];
1196 MonoILExceptionInfo * ex_info;
1197 MonoILExceptionBlock * ex_block;
1200 stream_data_align (&assembly->code);
1201 /* always use fat format for now */
1202 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1203 num_exception *= 6 * sizeof (guint32);
1204 num_exception += 4; /* include the size of the header */
1205 sheader [1] = num_exception & 0xff;
1206 sheader [2] = (num_exception >> 8) & 0xff;
1207 sheader [3] = (num_exception >> 16) & 0xff;
1208 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1209 /* fat header, so we are already aligned */
1211 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1212 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1213 if (ex_info->handlers) {
1214 int finally_start = ex_info->start + ex_info->len;
1215 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1217 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1219 val = GUINT32_TO_LE (ex_block->type);
1220 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1222 val = GUINT32_TO_LE (ex_info->start);
1223 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1224 /* need fault, too, probably */
1225 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1226 val = GUINT32_TO_LE (finally_start - ex_info->start);
1228 val = GUINT32_TO_LE (ex_info->len);
1229 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1230 /* handler offset */
1231 val = GUINT32_TO_LE (ex_block->start);
1232 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1234 val = GUINT32_TO_LE (ex_block->len);
1235 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1236 finally_start = ex_block->start + ex_block->len;
1237 if (ex_block->extype) {
1238 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1240 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1241 val = ex_block->filter_offset;
1245 val = GUINT32_TO_LE (val);
1246 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1247 /*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",
1248 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);*/
1251 g_error ("No clauses for ex info block %d", i);
1255 return assembly->text_rva + idx;
1259 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1261 MONO_REQ_GC_NEUTRAL_MODE;
1264 MonoDynamicTable *table;
1267 table = &assembly->tables [table_idx];
1269 g_assert (col < table->columns);
1271 values = table->values + table->columns;
1272 for (i = 1; i <= table->rows; ++i) {
1273 if (values [col] == token)
1275 values += table->columns;
1281 * LOCKING: Acquires the loader lock.
1283 static MonoCustomAttrInfo*
1284 lookup_custom_attr (MonoImage *image, gpointer member)
1286 MONO_REQ_GC_NEUTRAL_MODE;
1288 MonoCustomAttrInfo* res;
1290 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1295 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1301 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1303 MONO_REQ_GC_UNSAFE_MODE;
1305 /* FIXME: Need to do more checks */
1306 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1307 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1309 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1316 static MonoCustomAttrInfo*
1317 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1319 MONO_REQ_GC_UNSAFE_MODE;
1321 int i, index, count, not_visible;
1322 MonoCustomAttrInfo *ainfo;
1323 MonoReflectionCustomAttr *cattr;
1327 /* FIXME: check in assembly the Run flag is set */
1329 count = mono_array_length (cattrs);
1331 /* Skip nonpublic attributes since MS.NET seems to do the same */
1332 /* FIXME: This needs to be done more globally */
1334 for (i = 0; i < count; ++i) {
1335 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1336 if (!custom_attr_visible (image, cattr))
1339 count -= not_visible;
1341 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1343 ainfo->image = image;
1344 ainfo->num_attrs = count;
1345 ainfo->cached = alloc_img != NULL;
1347 for (i = 0; i < count; ++i) {
1348 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1349 if (custom_attr_visible (image, cattr)) {
1350 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1351 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1352 ainfo->attrs [index].ctor = cattr->ctor->method;
1353 ainfo->attrs [index].data = saved;
1354 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1362 #ifndef DISABLE_REFLECTION_EMIT
1364 * LOCKING: Acquires the loader lock.
1367 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1369 MONO_REQ_GC_UNSAFE_MODE;
1371 MonoCustomAttrInfo *ainfo, *tmp;
1373 if (!cattrs || !mono_array_length (cattrs))
1376 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1378 mono_loader_lock ();
1379 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1381 mono_custom_attrs_free (tmp);
1382 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1383 mono_loader_unlock ();
1389 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1391 MONO_REQ_GC_NEUTRAL_MODE;
1398 * idx is the table index of the object
1399 * type is one of MONO_CUSTOM_ATTR_*
1402 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1404 MONO_REQ_GC_UNSAFE_MODE;
1406 MonoDynamicTable *table;
1407 MonoReflectionCustomAttr *cattr;
1409 guint32 count, i, token;
1411 char *p = blob_size;
1413 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1416 count = mono_array_length (cattrs);
1417 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1418 table->rows += count;
1419 alloc_table (table, table->rows);
1420 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1421 idx <<= MONO_CUSTOM_ATTR_BITS;
1423 for (i = 0; i < count; ++i) {
1424 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1425 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1426 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1427 type = mono_metadata_token_index (token);
1428 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1429 switch (mono_metadata_token_table (token)) {
1430 case MONO_TABLE_METHOD:
1431 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1433 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1434 * method, not the one returned by mono_image_create_token ().
1436 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1438 case MONO_TABLE_MEMBERREF:
1439 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1442 g_warning ("got wrong token in custom attr");
1445 values [MONO_CUSTOM_ATTR_TYPE] = type;
1447 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1448 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1449 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1450 values += MONO_CUSTOM_ATTR_SIZE;
1456 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1458 MONO_REQ_GC_UNSAFE_MODE;
1460 MonoDynamicTable *table;
1462 guint32 count, i, idx;
1463 MonoReflectionPermissionSet *perm;
1468 count = mono_array_length (permissions);
1469 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1470 table->rows += count;
1471 alloc_table (table, table->rows);
1473 for (i = 0; i < mono_array_length (permissions); ++i) {
1474 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1476 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1478 idx = mono_metadata_token_index (parent_token);
1479 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1480 switch (mono_metadata_token_table (parent_token)) {
1481 case MONO_TABLE_TYPEDEF:
1482 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1484 case MONO_TABLE_METHOD:
1485 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1487 case MONO_TABLE_ASSEMBLY:
1488 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1491 g_assert_not_reached ();
1494 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1495 values [MONO_DECL_SECURITY_PARENT] = idx;
1496 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1503 * Fill in the MethodDef and ParamDef tables for a method.
1504 * This is used for both normal methods and constructors.
1507 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1509 MONO_REQ_GC_UNSAFE_MODE;
1511 MonoDynamicTable *table;
1515 /* room in this table is already allocated */
1516 table = &assembly->tables [MONO_TABLE_METHOD];
1517 *mb->table_idx = table->next_idx ++;
1518 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1519 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1520 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1521 values [MONO_METHOD_FLAGS] = mb->attrs;
1522 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1523 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1524 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1526 table = &assembly->tables [MONO_TABLE_PARAM];
1527 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1529 mono_image_add_decl_security (assembly,
1530 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1533 MonoDynamicTable *mtable;
1536 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1537 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1540 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1541 if (mono_array_get (mb->pinfo, gpointer, i))
1544 table->rows += count;
1545 alloc_table (table, table->rows);
1546 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1547 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1548 MonoReflectionParamBuilder *pb;
1549 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1550 values [MONO_PARAM_FLAGS] = pb->attrs;
1551 values [MONO_PARAM_SEQUENCE] = i;
1552 if (pb->name != NULL) {
1553 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1555 values [MONO_PARAM_NAME] = 0;
1557 values += MONO_PARAM_SIZE;
1558 if (pb->marshal_info) {
1560 alloc_table (mtable, mtable->rows);
1561 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1562 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1563 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1565 pb->table_idx = table->next_idx++;
1566 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1567 guint32 field_type = 0;
1568 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1570 alloc_table (mtable, mtable->rows);
1571 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1572 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1573 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1574 mvalues [MONO_CONSTANT_TYPE] = field_type;
1575 mvalues [MONO_CONSTANT_PADDING] = 0;
1582 #ifndef DISABLE_REFLECTION_EMIT
1584 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1586 MONO_REQ_GC_UNSAFE_MODE;
1588 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1590 rmb->ilgen = mb->ilgen;
1591 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1592 rmb->parameters = mb->parameters;
1593 rmb->generic_params = mb->generic_params;
1594 rmb->generic_container = mb->generic_container;
1595 rmb->opt_types = NULL;
1596 rmb->pinfo = mb->pinfo;
1597 rmb->attrs = mb->attrs;
1598 rmb->iattrs = mb->iattrs;
1599 rmb->call_conv = mb->call_conv;
1600 rmb->code = mb->code;
1601 rmb->type = mb->type;
1602 rmb->name = mb->name;
1603 rmb->table_idx = &mb->table_idx;
1604 rmb->init_locals = mb->init_locals;
1605 rmb->skip_visibility = FALSE;
1606 rmb->return_modreq = mb->return_modreq;
1607 rmb->return_modopt = mb->return_modopt;
1608 rmb->param_modreq = mb->param_modreq;
1609 rmb->param_modopt = mb->param_modopt;
1610 rmb->permissions = mb->permissions;
1611 rmb->mhandle = mb->mhandle;
1616 rmb->charset = mb->charset;
1617 rmb->extra_flags = mb->extra_flags;
1618 rmb->native_cc = mb->native_cc;
1619 rmb->dllentry = mb->dllentry;
1625 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1627 MONO_REQ_GC_UNSAFE_MODE;
1629 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1631 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1633 rmb->ilgen = mb->ilgen;
1634 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1635 rmb->parameters = mb->parameters;
1636 rmb->generic_params = NULL;
1637 rmb->generic_container = NULL;
1638 rmb->opt_types = NULL;
1639 rmb->pinfo = mb->pinfo;
1640 rmb->attrs = mb->attrs;
1641 rmb->iattrs = mb->iattrs;
1642 rmb->call_conv = mb->call_conv;
1644 rmb->type = mb->type;
1645 rmb->name = mono_string_new (mono_domain_get (), name);
1646 rmb->table_idx = &mb->table_idx;
1647 rmb->init_locals = mb->init_locals;
1648 rmb->skip_visibility = FALSE;
1649 rmb->return_modreq = NULL;
1650 rmb->return_modopt = NULL;
1651 rmb->param_modreq = mb->param_modreq;
1652 rmb->param_modopt = mb->param_modopt;
1653 rmb->permissions = mb->permissions;
1654 rmb->mhandle = mb->mhandle;
1660 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1662 MONO_REQ_GC_UNSAFE_MODE;
1664 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1666 rmb->ilgen = mb->ilgen;
1667 rmb->rtype = mb->rtype;
1668 rmb->parameters = mb->parameters;
1669 rmb->generic_params = NULL;
1670 rmb->generic_container = NULL;
1671 rmb->opt_types = NULL;
1673 rmb->attrs = mb->attrs;
1675 rmb->call_conv = mb->call_conv;
1677 rmb->type = (MonoObject *) mb->owner;
1678 rmb->name = mb->name;
1679 rmb->table_idx = NULL;
1680 rmb->init_locals = mb->init_locals;
1681 rmb->skip_visibility = mb->skip_visibility;
1682 rmb->return_modreq = NULL;
1683 rmb->return_modopt = NULL;
1684 rmb->param_modreq = NULL;
1685 rmb->param_modopt = NULL;
1686 rmb->permissions = NULL;
1687 rmb->mhandle = mb->mhandle;
1694 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1696 MONO_REQ_GC_UNSAFE_MODE;
1698 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1699 MonoDynamicTable *table;
1702 MonoReflectionMethod *m;
1705 if (!mb->override_methods)
1708 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1709 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1711 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1713 alloc_table (table, table->rows);
1714 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1715 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1716 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1718 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1719 switch (mono_metadata_token_table (tok)) {
1720 case MONO_TABLE_MEMBERREF:
1721 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1723 case MONO_TABLE_METHOD:
1724 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1727 g_assert_not_reached ();
1729 values [MONO_METHODIMPL_DECLARATION] = tok;
1733 #ifndef DISABLE_REFLECTION_EMIT
1735 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1737 MONO_REQ_GC_UNSAFE_MODE;
1739 MonoDynamicTable *table;
1741 ReflectionMethodBuilder rmb;
1744 reflection_methodbuilder_from_method_builder (&rmb, mb);
1746 mono_image_basic_method (&rmb, assembly);
1747 mb->table_idx = *rmb.table_idx;
1749 if (mb->dll) { /* It's a P/Invoke method */
1751 /* map CharSet values to on-disk values */
1752 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1753 int extra_flags = mb->extra_flags;
1754 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1759 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1760 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1762 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1764 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1765 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1766 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1767 table = &assembly->tables [MONO_TABLE_MODULEREF];
1769 alloc_table (table, table->rows);
1770 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1771 values [MONO_IMPLMAP_SCOPE] = table->rows;
1775 if (mb->generic_params) {
1776 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1777 table->rows += mono_array_length (mb->generic_params);
1778 alloc_table (table, table->rows);
1779 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1780 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1782 mono_image_get_generic_param_info (
1783 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1790 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1792 MONO_REQ_GC_UNSAFE_MODE;
1794 ReflectionMethodBuilder rmb;
1796 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1798 mono_image_basic_method (&rmb, assembly);
1799 mb->table_idx = *rmb.table_idx;
1804 type_get_fully_qualified_name (MonoType *type)
1806 MONO_REQ_GC_NEUTRAL_MODE;
1808 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1812 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1814 MONO_REQ_GC_UNSAFE_MODE;
1819 klass = mono_class_from_mono_type (type);
1821 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1822 ta = klass->image->assembly;
1823 if (assembly_is_dynamic (ta) || (ta == ass)) {
1824 if (klass->generic_class || klass->generic_container)
1825 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1826 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1828 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1831 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1834 #ifndef DISABLE_REFLECTION_EMIT
1835 /*field_image is the image to which the eventual custom mods have been encoded against*/
1837 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1839 MONO_REQ_GC_NEUTRAL_MODE;
1842 guint32 idx, i, token;
1844 if (!assembly->save)
1847 sigbuffer_init (&buf, 32);
1849 sigbuffer_add_value (&buf, 0x06);
1850 /* encode custom attributes before the type */
1851 if (type->num_mods) {
1852 for (i = 0; i < type->num_mods; ++i) {
1855 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1856 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1858 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1860 token = type->modifiers [i].token;
1863 if (type->modifiers [i].required)
1864 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1866 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1868 sigbuffer_add_value (&buf, token);
1871 encode_type (assembly, type, &buf);
1872 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1873 sigbuffer_free (&buf);
1879 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1881 MONO_REQ_GC_UNSAFE_MODE;
1885 guint32 typespec = 0;
1889 init_type_builder_generics (fb->type);
1891 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1892 class = mono_class_from_mono_type (type);
1894 sigbuffer_init (&buf, 32);
1896 sigbuffer_add_value (&buf, 0x06);
1897 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1898 /* encode custom attributes before the type */
1900 if (class->generic_container)
1901 typespec = create_typespec (assembly, type);
1904 MonoGenericClass *gclass;
1905 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1906 encode_generic_class (assembly, gclass, &buf);
1908 encode_type (assembly, type, &buf);
1910 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1911 sigbuffer_free (&buf);
1916 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1918 MONO_REQ_GC_UNSAFE_MODE;
1920 char blob_size [64];
1921 char *b = blob_size;
1924 guint32 idx = 0, len = 0, dummy = 0;
1926 buf = g_malloc (64);
1928 *ret_type = MONO_TYPE_CLASS;
1930 box_val = (char*)&dummy;
1932 box_val = ((char*)val) + sizeof (MonoObject);
1933 *ret_type = val->vtable->klass->byval_arg.type;
1936 switch (*ret_type) {
1937 case MONO_TYPE_BOOLEAN:
1942 case MONO_TYPE_CHAR:
1959 case MONO_TYPE_VALUETYPE: {
1960 MonoClass *klass = val->vtable->klass;
1962 if (klass->enumtype) {
1963 *ret_type = mono_class_enum_basetype (klass)->type;
1965 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1968 g_error ("we can't encode valuetypes, we should have never reached this line");
1971 case MONO_TYPE_CLASS:
1973 case MONO_TYPE_STRING: {
1974 MonoString *str = (MonoString*)val;
1975 /* there is no signature */
1976 len = str->length * 2;
1977 mono_metadata_encode_value (len, b, &b);
1978 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1980 char *swapped = g_malloc (2 * mono_string_length (str));
1981 const char *p = (const char*)mono_string_chars (str);
1983 swap_with_size (swapped, p, 2, mono_string_length (str));
1984 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1988 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1994 case MONO_TYPE_GENERICINST:
1995 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1998 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2001 /* there is no signature */
2002 mono_metadata_encode_value (len, b, &b);
2003 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2004 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2005 swap_with_size (blob_size, box_val, len, 1);
2006 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2008 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2016 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2018 MONO_REQ_GC_UNSAFE_MODE;
2024 sigbuffer_init (&buf, 32);
2026 sigbuffer_add_value (&buf, minfo->type);
2028 switch (minfo->type) {
2029 case MONO_NATIVE_BYVALTSTR:
2030 case MONO_NATIVE_BYVALARRAY:
2031 sigbuffer_add_value (&buf, minfo->count);
2033 case MONO_NATIVE_LPARRAY:
2034 if (minfo->eltype || minfo->has_size) {
2035 sigbuffer_add_value (&buf, minfo->eltype);
2036 if (minfo->has_size) {
2037 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2038 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2040 /* LAMESPEC: ElemMult is undocumented */
2041 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2045 case MONO_NATIVE_SAFEARRAY:
2047 sigbuffer_add_value (&buf, minfo->eltype);
2049 case MONO_NATIVE_CUSTOM:
2051 str = mono_string_to_utf8 (minfo->guid);
2053 sigbuffer_add_value (&buf, len);
2054 sigbuffer_add_mem (&buf, str, len);
2057 sigbuffer_add_value (&buf, 0);
2059 /* native type name */
2060 sigbuffer_add_value (&buf, 0);
2061 /* custom marshaler type name */
2062 if (minfo->marshaltype || minfo->marshaltyperef) {
2063 if (minfo->marshaltyperef)
2064 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2066 str = mono_string_to_utf8 (minfo->marshaltype);
2068 sigbuffer_add_value (&buf, len);
2069 sigbuffer_add_mem (&buf, str, len);
2072 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2073 sigbuffer_add_value (&buf, 0);
2075 if (minfo->mcookie) {
2076 str = mono_string_to_utf8 (minfo->mcookie);
2078 sigbuffer_add_value (&buf, len);
2079 sigbuffer_add_mem (&buf, str, len);
2082 sigbuffer_add_value (&buf, 0);
2088 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089 sigbuffer_free (&buf);
2094 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2096 MONO_REQ_GC_UNSAFE_MODE;
2098 MonoDynamicTable *table;
2101 /* maybe this fixup should be done in the C# code */
2102 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2103 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2104 table = &assembly->tables [MONO_TABLE_FIELD];
2105 fb->table_idx = table->next_idx ++;
2106 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2107 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2108 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2109 values [MONO_FIELD_FLAGS] = fb->attrs;
2110 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2112 if (fb->offset != -1) {
2113 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2115 alloc_table (table, table->rows);
2116 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2117 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2118 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2120 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2121 guint32 field_type = 0;
2122 table = &assembly->tables [MONO_TABLE_CONSTANT];
2124 alloc_table (table, table->rows);
2125 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2126 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2127 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2128 values [MONO_CONSTANT_TYPE] = field_type;
2129 values [MONO_CONSTANT_PADDING] = 0;
2131 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2133 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2135 alloc_table (table, table->rows);
2136 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2137 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2139 * We store it in the code section because it's simpler for now.
2142 if (mono_array_length (fb->rva_data) >= 10)
2143 stream_data_align (&assembly->code);
2144 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2146 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2147 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2149 if (fb->marshal_info) {
2150 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2152 alloc_table (table, table->rows);
2153 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2154 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2155 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2160 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2162 MONO_REQ_GC_UNSAFE_MODE;
2165 guint32 nparams = 0;
2166 MonoReflectionMethodBuilder *mb = fb->get_method;
2167 MonoReflectionMethodBuilder *smb = fb->set_method;
2170 if (mb && mb->parameters)
2171 nparams = mono_array_length (mb->parameters);
2172 if (!mb && smb && smb->parameters)
2173 nparams = mono_array_length (smb->parameters) - 1;
2174 sigbuffer_init (&buf, 32);
2175 if (fb->call_conv & 0x20)
2176 sigbuffer_add_byte (&buf, 0x28);
2178 sigbuffer_add_byte (&buf, 0x08);
2179 sigbuffer_add_value (&buf, nparams);
2181 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2182 for (i = 0; i < nparams; ++i) {
2183 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2184 encode_reflection_type (assembly, pt, &buf);
2186 } else if (smb && smb->parameters) {
2187 /* the property type is the last param */
2188 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2189 for (i = 0; i < nparams; ++i) {
2190 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2191 encode_reflection_type (assembly, pt, &buf);
2194 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2197 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2198 sigbuffer_free (&buf);
2203 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2205 MONO_REQ_GC_UNSAFE_MODE;
2207 MonoDynamicTable *table;
2209 guint num_methods = 0;
2213 * we need to set things in the following tables:
2214 * PROPERTYMAP (info already filled in _get_type_info ())
2215 * PROPERTY (rows already preallocated in _get_type_info ())
2216 * METHOD (method info already done with the generic method code)
2220 table = &assembly->tables [MONO_TABLE_PROPERTY];
2221 pb->table_idx = table->next_idx ++;
2222 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2223 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2224 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2225 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2227 /* FIXME: we still don't handle 'other' methods */
2228 if (pb->get_method) num_methods ++;
2229 if (pb->set_method) num_methods ++;
2231 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2232 table->rows += num_methods;
2233 alloc_table (table, table->rows);
2235 if (pb->get_method) {
2236 semaidx = table->next_idx ++;
2237 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2238 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2239 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2240 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2242 if (pb->set_method) {
2243 semaidx = table->next_idx ++;
2244 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2245 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2246 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2247 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2249 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2250 guint32 field_type = 0;
2251 table = &assembly->tables [MONO_TABLE_CONSTANT];
2253 alloc_table (table, table->rows);
2254 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2255 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2256 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2257 values [MONO_CONSTANT_TYPE] = field_type;
2258 values [MONO_CONSTANT_PADDING] = 0;
2263 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2265 MONO_REQ_GC_UNSAFE_MODE;
2267 MonoDynamicTable *table;
2269 guint num_methods = 0;
2273 * we need to set things in the following tables:
2274 * EVENTMAP (info already filled in _get_type_info ())
2275 * EVENT (rows already preallocated in _get_type_info ())
2276 * METHOD (method info already done with the generic method code)
2279 table = &assembly->tables [MONO_TABLE_EVENT];
2280 eb->table_idx = table->next_idx ++;
2281 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2282 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2283 values [MONO_EVENT_FLAGS] = eb->attrs;
2284 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2287 * FIXME: we still don't handle 'other' methods
2289 if (eb->add_method) num_methods ++;
2290 if (eb->remove_method) num_methods ++;
2291 if (eb->raise_method) num_methods ++;
2293 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2294 table->rows += num_methods;
2295 alloc_table (table, table->rows);
2297 if (eb->add_method) {
2298 semaidx = table->next_idx ++;
2299 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2300 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2301 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2302 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2304 if (eb->remove_method) {
2305 semaidx = table->next_idx ++;
2306 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2307 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2308 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2309 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2311 if (eb->raise_method) {
2312 semaidx = table->next_idx ++;
2313 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2314 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2315 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2316 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2321 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2323 MONO_REQ_GC_UNSAFE_MODE;
2325 MonoDynamicTable *table;
2326 guint32 num_constraints, i;
2330 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2331 num_constraints = gparam->iface_constraints ?
2332 mono_array_length (gparam->iface_constraints) : 0;
2333 table->rows += num_constraints;
2334 if (gparam->base_type)
2336 alloc_table (table, table->rows);
2338 if (gparam->base_type) {
2339 table_idx = table->next_idx ++;
2340 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2342 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2343 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2344 assembly, mono_reflection_type_get_handle (gparam->base_type));
2347 for (i = 0; i < num_constraints; i++) {
2348 MonoReflectionType *constraint = mono_array_get (
2349 gparam->iface_constraints, gpointer, i);
2351 table_idx = table->next_idx ++;
2352 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2354 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2355 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2356 assembly, mono_reflection_type_get_handle (constraint));
2361 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2363 MONO_REQ_GC_UNSAFE_MODE;
2365 GenericParamTableEntry *entry;
2368 * The GenericParam table must be sorted according to the `owner' field.
2369 * We need to do this sorting prior to writing the GenericParamConstraint
2370 * table, since we have to use the final GenericParam table indices there
2371 * and they must also be sorted.
2374 entry = g_new0 (GenericParamTableEntry, 1);
2375 entry->owner = owner;
2376 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2377 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2378 entry->gparam = gparam;
2380 g_ptr_array_add (assembly->gen_params, entry);
2384 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2386 MONO_REQ_GC_UNSAFE_MODE;
2388 MonoDynamicTable *table;
2389 MonoGenericParam *param;
2393 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2394 table_idx = table->next_idx ++;
2395 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2397 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2399 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2400 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2401 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2402 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2404 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2406 encode_constraints (entry->gparam, table_idx, assembly);
2410 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2412 MONO_REQ_GC_UNSAFE_MODE;
2414 MonoDynamicTable *table;
2417 guint32 cols [MONO_ASSEMBLY_SIZE];
2421 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2424 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2425 table = &assembly->tables [MONO_TABLE_MODULEREF];
2426 token = table->next_idx ++;
2428 alloc_table (table, table->rows);
2429 values = table->values + token * MONO_MODULEREF_SIZE;
2430 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2432 token <<= MONO_RESOLUTION_SCOPE_BITS;
2433 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2434 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2439 if (assembly_is_dynamic (image->assembly))
2441 memset (cols, 0, sizeof (cols));
2443 /* image->assembly->image is the manifest module */
2444 image = image->assembly->image;
2445 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2448 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2449 token = table->next_idx ++;
2451 alloc_table (table, table->rows);
2452 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2453 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2454 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2455 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2456 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2457 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2458 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2459 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2460 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2462 if (strcmp ("", image->assembly->aname.culture)) {
2463 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2464 image->assembly->aname.culture);
2467 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2468 guchar pubtoken [9];
2470 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2471 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2473 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2475 token <<= MONO_RESOLUTION_SCOPE_BITS;
2476 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2477 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2482 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2484 MONO_REQ_GC_NEUTRAL_MODE;
2486 MonoDynamicTable *table;
2491 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2494 sigbuffer_init (&buf, 32);
2495 switch (type->type) {
2496 case MONO_TYPE_FNPTR:
2498 case MONO_TYPE_SZARRAY:
2499 case MONO_TYPE_ARRAY:
2501 case MONO_TYPE_MVAR:
2502 case MONO_TYPE_GENERICINST:
2503 encode_type (assembly, type, &buf);
2505 case MONO_TYPE_CLASS:
2506 case MONO_TYPE_VALUETYPE: {
2507 MonoClass *k = mono_class_from_mono_type (type);
2508 if (!k || !k->generic_container) {
2509 sigbuffer_free (&buf);
2512 encode_type (assembly, type, &buf);
2516 sigbuffer_free (&buf);
2520 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2521 if (assembly->save) {
2522 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2523 alloc_table (table, table->rows + 1);
2524 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2525 values [MONO_TYPESPEC_SIGNATURE] = token;
2527 sigbuffer_free (&buf);
2529 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2530 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2536 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2538 MONO_REQ_GC_UNSAFE_MODE;
2540 MonoDynamicTable *table;
2542 guint32 token, scope, enclosing;
2545 /* if the type requires a typespec, we must try that first*/
2546 if (try_typespec && (token = create_typespec (assembly, type)))
2548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2551 klass = mono_class_from_mono_type (type);
2553 klass = mono_class_from_mono_type (type);
2556 * If it's in the same module and not a generic type parameter:
2558 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2559 (type->type != MONO_TYPE_MVAR)) {
2560 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2561 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2562 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2566 if (klass->nested_in) {
2567 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2568 /* get the typeref idx of the enclosing type */
2569 enclosing >>= MONO_TYPEDEFORREF_BITS;
2570 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2572 scope = resolution_scope_from_image (assembly, klass->image);
2574 table = &assembly->tables [MONO_TABLE_TYPEREF];
2575 if (assembly->save) {
2576 alloc_table (table, table->rows + 1);
2577 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2578 values [MONO_TYPEREF_SCOPE] = scope;
2579 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2580 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2582 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2583 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2585 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2590 * Despite the name, we handle also TypeSpec (with the above helper).
2593 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2595 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2598 #ifndef DISABLE_REFLECTION_EMIT
2600 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2602 MONO_REQ_GC_NEUTRAL_MODE;
2604 MonoDynamicTable *table;
2606 guint32 token, pclass;
2608 switch (parent & MONO_TYPEDEFORREF_MASK) {
2609 case MONO_TYPEDEFORREF_TYPEREF:
2610 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2612 case MONO_TYPEDEFORREF_TYPESPEC:
2613 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2615 case MONO_TYPEDEFORREF_TYPEDEF:
2616 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2619 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2622 /* extract the index */
2623 parent >>= MONO_TYPEDEFORREF_BITS;
2625 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2627 if (assembly->save) {
2628 alloc_table (table, table->rows + 1);
2629 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2630 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2631 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2632 values [MONO_MEMBERREF_SIGNATURE] = sig;
2635 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2642 * Insert a memberef row into the metadata: the token that point to the memberref
2643 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2644 * mono_image_get_fieldref_token()).
2645 * The sig param is an index to an already built signature.
2648 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2650 MONO_REQ_GC_NEUTRAL_MODE;
2652 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2653 return mono_image_add_memberef_row (assembly, parent, name, sig);
2658 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2660 MONO_REQ_GC_NEUTRAL_MODE;
2663 MonoMethodSignature *sig;
2665 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2667 if (create_typespec) {
2668 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2673 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2674 if (token && !create_typespec)
2677 g_assert (!method->is_inflated);
2680 * A methodref signature can't contain an unmanaged calling convention.
2682 sig = mono_metadata_signature_dup (mono_method_signature (method));
2683 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2684 sig->call_convention = MONO_CALL_DEFAULT;
2685 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2686 method->name, method_encode_signature (assembly, sig));
2688 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2691 if (create_typespec) {
2692 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2693 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2694 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2696 if (assembly->save) {
2699 alloc_table (table, table->rows + 1);
2700 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2701 values [MONO_METHODSPEC_METHOD] = token;
2702 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2705 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2707 /*methodspec and memberef tokens are diferent, */
2708 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2715 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2717 guint32 token, parent, sig;
2718 ReflectionMethodBuilder rmb;
2720 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2722 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2726 name = mono_string_to_utf8 (method->name);
2727 reflection_methodbuilder_from_method_builder (&rmb, method);
2730 * A methodref signature can't contain an unmanaged calling convention.
2731 * Since some flags are encoded as part of call_conv, we need to check against it.
2733 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2734 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2736 sig = method_builder_encode_signature (assembly, &rmb);
2738 if (tb->generic_params)
2739 parent = create_generic_typespec (assembly, tb);
2741 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2743 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2746 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2751 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2752 const gchar *name, guint32 sig)
2754 MonoDynamicTable *table;
2758 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2760 if (assembly->save) {
2761 alloc_table (table, table->rows + 1);
2762 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2763 values [MONO_MEMBERREF_CLASS] = original;
2764 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2765 values [MONO_MEMBERREF_SIGNATURE] = sig;
2768 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2775 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2779 guint32 nparams = mono_array_length (mb->generic_params);
2782 if (!assembly->save)
2785 sigbuffer_init (&buf, 32);
2787 sigbuffer_add_value (&buf, 0xa);
2788 sigbuffer_add_value (&buf, nparams);
2790 for (i = 0; i < nparams; i++) {
2791 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2792 sigbuffer_add_value (&buf, i);
2795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2796 sigbuffer_free (&buf);
2801 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2803 MonoDynamicTable *table;
2805 guint32 token, mtoken = 0;
2807 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2811 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2813 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2814 switch (mono_metadata_token_table (mtoken)) {
2815 case MONO_TABLE_MEMBERREF:
2816 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2818 case MONO_TABLE_METHOD:
2819 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2822 g_assert_not_reached ();
2825 if (assembly->save) {
2826 alloc_table (table, table->rows + 1);
2827 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2828 values [MONO_METHODSPEC_METHOD] = mtoken;
2829 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2832 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2835 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2840 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2844 if (mb->generic_params && create_methodspec)
2845 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2847 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2851 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2852 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2857 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2859 guint32 token, parent, sig;
2860 ReflectionMethodBuilder rmb;
2862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2864 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2868 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2870 if (tb->generic_params)
2871 parent = create_generic_typespec (assembly, tb);
2873 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2875 name = mono_string_to_utf8 (rmb.name);
2876 sig = method_builder_encode_signature (assembly, &rmb);
2878 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2881 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2887 is_field_on_inst (MonoClassField *field)
2889 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2893 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2896 get_field_on_inst_generic_type (MonoClassField *field)
2898 MonoClass *class, *gtd;
2899 MonoDynamicGenericClass *dgclass;
2902 g_assert (is_field_on_inst (field));
2904 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2906 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2907 field_index = field - dgclass->fields;
2908 return dgclass->field_generic_types [field_index];
2911 class = field->parent;
2912 gtd = class->generic_class->container_class;
2914 if (field >= class->fields && field - class->fields < class->field.count) {
2915 field_index = field - class->fields;
2916 return gtd->fields [field_index].type;
2919 g_assert_not_reached ();
2923 #ifndef DISABLE_REFLECTION_EMIT
2925 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2931 g_assert (field->parent);
2933 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2937 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2938 int index = field - field->parent->fields;
2939 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2941 if (is_field_on_inst (field))
2942 type = get_field_on_inst_generic_type (field);
2944 type = mono_field_get_type (field);
2946 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2947 mono_field_get_name (field),
2948 fieldref_encode_signature (assembly, field->parent->image, type));
2949 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2954 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2958 MonoGenericClass *gclass;
2962 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2965 if (is_sre_field_builder (mono_object_class (f->fb))) {
2966 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2967 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2968 klass = mono_class_from_mono_type (type);
2969 gclass = type->data.generic_class;
2970 g_assert (gclass->is_dynamic);
2972 name = mono_string_to_utf8 (fb->name);
2973 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2974 field_encode_signature (assembly, fb));
2976 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2978 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2980 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2981 klass = mono_class_from_mono_type (type);
2983 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2984 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2986 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2987 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2990 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2995 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2999 MonoGenericClass *gclass;
3002 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3004 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3008 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3009 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3010 ReflectionMethodBuilder rmb;
3013 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3014 klass = mono_class_from_mono_type (type);
3016 gclass = type->data.generic_class;
3017 g_assert (gclass->is_dynamic);
3019 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3021 name = mono_string_to_utf8 (rmb.name);
3023 sig = method_builder_encode_signature (assembly, &rmb);
3025 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3027 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3028 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3030 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3031 klass = mono_class_from_mono_type (type);
3033 sig = method_encode_signature (assembly, mono_method_signature (mm));
3034 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3036 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3037 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3041 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3046 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3050 MonoGenericContext tmp_context;
3051 MonoType **type_argv;
3052 MonoGenericInst *ginst;
3053 MonoMethod *method, *inflated;
3056 init_type_builder_generics ((MonoObject*)m->inst);
3058 method = inflate_method (m->inst, (MonoObject*)m->mb);
3060 klass = method->klass;
3062 if (m->method_args == NULL)
3065 if (method->is_inflated)
3066 method = ((MonoMethodInflated *) method)->declaring;
3068 count = mono_array_length (m->method_args);
3070 type_argv = g_new0 (MonoType *, count);
3071 for (i = 0; i < count; i++) {
3072 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3073 type_argv [i] = mono_reflection_type_get_handle (garg);
3075 ginst = mono_metadata_get_generic_inst (count, type_argv);
3078 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3079 tmp_context.method_inst = ginst;
3081 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3082 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3087 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3089 guint32 sig, token = 0;
3093 if (m->method_args) {
3094 MonoMethod *inflated;
3096 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3097 if (create_methodspec)
3098 token = mono_image_get_methodspec_token (assembly, inflated);
3100 token = mono_image_get_inflated_method_token (assembly, inflated);
3104 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3108 if (is_sre_method_builder (mono_object_class (m->mb))) {
3109 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3110 MonoGenericClass *gclass;
3111 ReflectionMethodBuilder rmb;
3114 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3115 klass = mono_class_from_mono_type (type);
3116 gclass = type->data.generic_class;
3117 g_assert (gclass->is_dynamic);
3119 reflection_methodbuilder_from_method_builder (&rmb, mb);
3121 name = mono_string_to_utf8 (rmb.name);
3123 sig = method_builder_encode_signature (assembly, &rmb);
3125 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3127 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3128 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3130 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3131 klass = mono_class_from_mono_type (type);
3133 sig = method_encode_signature (assembly, mono_method_signature (mm));
3134 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3136 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3137 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3140 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3145 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3149 guint32 nparams = context->method_inst->type_argc;
3152 if (!assembly->save)
3155 sigbuffer_init (&buf, 32);
3157 * FIXME: vararg, explicit_this, differenc call_conv values...
3159 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3160 sigbuffer_add_value (&buf, nparams);
3162 for (i = 0; i < nparams; i++)
3163 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3165 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3166 sigbuffer_free (&buf);
3171 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3173 MonoDynamicTable *table;
3175 guint32 token, mtoken = 0, sig;
3176 MonoMethodInflated *imethod;
3177 MonoMethod *declaring;
3179 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3181 g_assert (method->is_inflated);
3182 imethod = (MonoMethodInflated *) method;
3183 declaring = imethod->declaring;
3185 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3186 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3188 if (!mono_method_signature (declaring)->generic_param_count)
3191 switch (mono_metadata_token_table (mtoken)) {
3192 case MONO_TABLE_MEMBERREF:
3193 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3195 case MONO_TABLE_METHOD:
3196 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3199 g_assert_not_reached ();
3202 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3204 if (assembly->save) {
3205 alloc_table (table, table->rows + 1);
3206 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3207 values [MONO_METHODSPEC_METHOD] = mtoken;
3208 values [MONO_METHODSPEC_SIGNATURE] = sig;
3211 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3218 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3220 MonoMethodInflated *imethod;
3223 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3227 g_assert (method->is_inflated);
3228 imethod = (MonoMethodInflated *) method;
3230 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3231 token = method_encode_methodspec (assembly, method);
3233 guint32 sig = method_encode_signature (
3234 assembly, mono_method_signature (imethod->declaring));
3235 token = mono_image_get_memberref_token (
3236 assembly, &method->klass->byval_arg, method->name, sig);
3239 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3244 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3246 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3249 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3250 token = mono_image_get_memberref_token (
3251 assembly, &m->klass->byval_arg, m->name, sig);
3257 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3259 MonoDynamicTable *table;
3268 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3269 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3270 * Because of this, we must not insert it into the `typeref' hash table.
3272 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3273 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3277 sigbuffer_init (&buf, 32);
3279 g_assert (tb->generic_params);
3280 klass = mono_class_from_mono_type (type);
3282 if (tb->generic_container)
3283 mono_reflection_create_generic_class (tb);
3285 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3286 g_assert (klass->generic_container);
3287 sigbuffer_add_value (&buf, klass->byval_arg.type);
3288 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3290 count = mono_array_length (tb->generic_params);
3291 sigbuffer_add_value (&buf, count);
3292 for (i = 0; i < count; i++) {
3293 MonoReflectionGenericParam *gparam;
3295 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3297 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3300 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3302 if (assembly->save) {
3303 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3304 alloc_table (table, table->rows + 1);
3305 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3306 values [MONO_TYPESPEC_SIGNATURE] = token;
3308 sigbuffer_free (&buf);
3310 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3311 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3317 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3320 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3322 int i, count, len, pos;
3327 count += mono_array_length (modreq);
3329 count += mono_array_length (modopt);
3332 return mono_metadata_type_dup (NULL, type);
3334 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3336 memcpy (t, type, MONO_SIZEOF_TYPE);
3338 t->num_mods = count;
3341 for (i = 0; i < mono_array_length (modreq); ++i) {
3342 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3343 t->modifiers [pos].required = 1;
3344 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3349 for (i = 0; i < mono_array_length (modopt); ++i) {
3350 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3351 t->modifiers [pos].required = 0;
3352 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3361 init_type_builder_generics (MonoObject *type)
3363 MonoReflectionTypeBuilder *tb;
3365 if (!is_sre_type_builder(mono_object_class (type)))
3367 tb = (MonoReflectionTypeBuilder *)type;
3369 if (tb && tb->generic_container)
3370 mono_reflection_create_generic_class (tb);
3374 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3376 MonoDynamicTable *table;
3377 MonoType *custom = NULL, *type;
3379 guint32 token, pclass, parent, sig;
3382 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3386 /* FIXME: is this call necessary? */
3387 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3388 name = mono_string_to_utf8 (fb->name);
3390 /*FIXME this is one more layer of ugliness due how types are created.*/
3391 init_type_builder_generics (fb->type);
3393 /* fb->type does not include the custom modifiers */
3394 /* FIXME: We should do this in one place when a fieldbuilder is created */
3395 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3396 if (fb->modreq || fb->modopt)
3397 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3399 sig = fieldref_encode_signature (assembly, NULL, type);
3402 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3403 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3405 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3406 parent >>= MONO_TYPEDEFORREF_BITS;
3408 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3410 if (assembly->save) {
3411 alloc_table (table, table->rows + 1);
3412 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3413 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3414 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3415 values [MONO_MEMBERREF_SIGNATURE] = sig;
3418 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3420 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3426 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3432 if (!assembly->save)
3435 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3436 g_assert (helper->type == 2);
3438 if (helper->arguments)
3439 nargs = mono_array_length (helper->arguments);
3443 sigbuffer_init (&buf, 32);
3445 /* Encode calling convention */
3446 /* Change Any to Standard */
3447 if ((helper->call_conv & 0x03) == 0x03)
3448 helper->call_conv = 0x01;
3449 /* explicit_this implies has_this */
3450 if (helper->call_conv & 0x40)
3451 helper->call_conv &= 0x20;
3453 if (helper->call_conv == 0) { /* Unmanaged */
3454 idx = helper->unmanaged_call_conv - 1;
3457 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3458 if (helper->call_conv & 0x02) /* varargs */
3462 sigbuffer_add_byte (&buf, idx);
3463 sigbuffer_add_value (&buf, nargs);
3464 encode_reflection_type (assembly, helper->return_type, &buf);
3465 for (i = 0; i < nargs; ++i) {
3466 MonoArray *modreqs = NULL;
3467 MonoArray *modopts = NULL;
3468 MonoReflectionType *pt;
3470 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3471 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3472 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3473 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3475 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3476 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3477 encode_reflection_type (assembly, pt, &buf);
3479 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3480 sigbuffer_free (&buf);
3486 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3489 MonoDynamicTable *table;
3492 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3493 idx = table->next_idx ++;
3495 alloc_table (table, table->rows);
3496 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3498 values [MONO_STAND_ALONE_SIGNATURE] =
3499 mono_reflection_encode_sighelper (assembly, helper);
3505 reflection_cc_to_file (int call_conv) {
3506 switch (call_conv & 0x3) {
3508 case 1: return MONO_CALL_DEFAULT;
3509 case 2: return MONO_CALL_VARARG;
3511 g_assert_not_reached ();
3515 #endif /* !DISABLE_REFLECTION_EMIT */
3519 MonoMethodSignature *sig;
3524 #ifndef DISABLE_REFLECTION_EMIT
3526 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3531 MonoMethodSignature *sig;
3535 name = mono_string_to_utf8 (m->name);
3536 nparams = mono_array_length (m->parameters);
3537 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3539 sig->sentinelpos = -1;
3540 sig->call_convention = reflection_cc_to_file (m->call_conv);
3541 sig->param_count = nparams;
3542 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3543 mtype = mono_reflection_type_get_handle (m->parent);
3544 for (i = 0; i < nparams; ++i)
3545 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3547 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3549 if (strcmp (name, am->name) == 0 &&
3550 mono_metadata_type_equal (am->parent, mtype) &&
3551 mono_metadata_signature_equal (am->sig, sig)) {
3554 m->table_idx = am->token & 0xffffff;
3558 am = g_new0 (ArrayMethod, 1);
3562 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3563 method_encode_signature (assembly, sig));
3564 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3565 m->table_idx = am->token & 0xffffff;
3570 * Insert into the metadata tables all the info about the TypeBuilder tb.
3571 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3574 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3576 MonoDynamicTable *table;
3578 int i, is_object = 0, is_system = 0;
3581 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3582 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3583 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3584 n = mono_string_to_utf8 (tb->name);
3585 if (strcmp (n, "Object") == 0)
3587 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3589 n = mono_string_to_utf8 (tb->nspace);
3590 if (strcmp (n, "System") == 0)
3592 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3594 if (tb->parent && !(is_system && is_object) &&
3595 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3596 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3598 values [MONO_TYPEDEF_EXTENDS] = 0;
3600 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3601 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3604 * if we have explicitlayout or sequentiallayouts, output data in the
3605 * ClassLayout table.
3607 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3608 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3609 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3611 alloc_table (table, table->rows);
3612 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3613 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3614 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3615 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3618 /* handle interfaces */
3619 if (tb->interfaces) {
3620 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3622 table->rows += mono_array_length (tb->interfaces);
3623 alloc_table (table, table->rows);
3624 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3625 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3626 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3627 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3628 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3629 values += MONO_INTERFACEIMPL_SIZE;
3635 table = &assembly->tables [MONO_TABLE_FIELD];
3636 table->rows += tb->num_fields;
3637 alloc_table (table, table->rows);
3638 for (i = 0; i < tb->num_fields; ++i)
3639 mono_image_get_field_info (
3640 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3643 /* handle constructors */
3645 table = &assembly->tables [MONO_TABLE_METHOD];
3646 table->rows += mono_array_length (tb->ctors);
3647 alloc_table (table, table->rows);
3648 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3649 mono_image_get_ctor_info (domain,
3650 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3653 /* handle methods */
3655 table = &assembly->tables [MONO_TABLE_METHOD];
3656 table->rows += tb->num_methods;
3657 alloc_table (table, table->rows);
3658 for (i = 0; i < tb->num_methods; ++i)
3659 mono_image_get_method_info (
3660 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3663 /* Do the same with properties etc.. */
3664 if (tb->events && mono_array_length (tb->events)) {
3665 table = &assembly->tables [MONO_TABLE_EVENT];
3666 table->rows += mono_array_length (tb->events);
3667 alloc_table (table, table->rows);
3668 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3670 alloc_table (table, table->rows);
3671 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3672 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3673 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3674 for (i = 0; i < mono_array_length (tb->events); ++i)
3675 mono_image_get_event_info (
3676 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3678 if (tb->properties && mono_array_length (tb->properties)) {
3679 table = &assembly->tables [MONO_TABLE_PROPERTY];
3680 table->rows += mono_array_length (tb->properties);
3681 alloc_table (table, table->rows);
3682 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3684 alloc_table (table, table->rows);
3685 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3686 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3687 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3688 for (i = 0; i < mono_array_length (tb->properties); ++i)
3689 mono_image_get_property_info (
3690 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3693 /* handle generic parameters */
3694 if (tb->generic_params) {
3695 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3696 table->rows += mono_array_length (tb->generic_params);
3697 alloc_table (table, table->rows);
3698 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3699 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3701 mono_image_get_generic_param_info (
3702 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3706 mono_image_add_decl_security (assembly,
3707 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3710 MonoDynamicTable *ntable;
3712 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3713 ntable->rows += mono_array_length (tb->subtypes);
3714 alloc_table (ntable, ntable->rows);
3715 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3717 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3718 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3720 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3721 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3722 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3723 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3724 mono_string_to_utf8 (tb->name), tb->table_idx,
3725 ntable->next_idx, ntable->rows);*/
3726 values += MONO_NESTED_CLASS_SIZE;
3734 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3738 mono_ptr_array_append (*types, type);
3740 if (!type->subtypes)
3743 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3744 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3745 collect_types (types, subtype);
3750 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3752 if ((*type1)->table_idx < (*type2)->table_idx)
3755 if ((*type1)->table_idx > (*type2)->table_idx)
3762 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3767 for (i = 0; i < mono_array_length (pinfo); ++i) {
3768 MonoReflectionParamBuilder *pb;
3769 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3772 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3777 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3780 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3782 for (i = 0; i < tb->num_fields; ++i) {
3783 MonoReflectionFieldBuilder* fb;
3784 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3785 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3789 for (i = 0; i < mono_array_length (tb->events); ++i) {
3790 MonoReflectionEventBuilder* eb;
3791 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3792 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3795 if (tb->properties) {
3796 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3797 MonoReflectionPropertyBuilder* pb;
3798 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3799 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3803 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3804 MonoReflectionCtorBuilder* cb;
3805 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3806 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3807 params_add_cattrs (assembly, cb->pinfo);
3812 for (i = 0; i < tb->num_methods; ++i) {
3813 MonoReflectionMethodBuilder* mb;
3814 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3815 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3816 params_add_cattrs (assembly, mb->pinfo);
3821 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3822 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3827 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3831 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3833 if (moduleb->global_methods) {
3834 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3835 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3836 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3837 params_add_cattrs (assembly, mb->pinfo);
3841 if (moduleb->global_fields) {
3842 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3843 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3844 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3848 if (moduleb->types) {
3849 for (i = 0; i < moduleb->num_types; ++i)
3850 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3855 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3857 MonoDynamicTable *table;
3861 char *b = blob_size;
3864 table = &assembly->tables [MONO_TABLE_FILE];
3866 alloc_table (table, table->rows);
3867 values = table->values + table->next_idx * MONO_FILE_SIZE;
3868 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3869 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3870 if (image_is_dynamic (module->image)) {
3871 /* This depends on the fact that the main module is emitted last */
3872 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3873 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3876 path = g_strdup (module->image->name);
3878 mono_sha1_get_digest_from_file (path, hash);
3881 mono_metadata_encode_value (20, b, &b);
3882 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3883 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3888 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3890 MonoDynamicTable *table;
3893 table = &assembly->tables [MONO_TABLE_MODULE];
3894 mb->table_idx = table->next_idx ++;
3895 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3896 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3899 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3900 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3901 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3902 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3906 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3907 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3909 MonoDynamicTable *table;
3913 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3914 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3917 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3919 alloc_table (table, table->rows);
3920 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3922 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3923 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3924 if (klass->nested_in)
3925 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3927 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3928 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3929 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3931 res = table->next_idx;
3935 /* Emit nested types */
3936 if (klass->ext && klass->ext->nested_classes) {
3939 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3940 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3947 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3948 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3953 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3955 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3957 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3958 parent_index, assembly);
3962 * We need to do this ourselves since klass->nested_classes is not set up.
3965 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3966 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3971 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3972 guint32 module_index, MonoDynamicImage *assembly)
3974 MonoImage *image = module->image;
3978 t = &image->tables [MONO_TABLE_TYPEDEF];
3980 for (i = 0; i < t->rows; ++i) {
3982 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3983 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3985 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3986 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3991 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3993 MonoDynamicTable *table;
3995 guint32 scope, scope_idx, impl, current_idx;
3996 gboolean forwarder = TRUE;
3997 gpointer iter = NULL;
4000 if (klass->nested_in) {
4001 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4004 scope = resolution_scope_from_image (assembly, klass->image);
4005 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4006 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4007 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4010 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4013 alloc_table (table, table->rows);
4014 current_idx = table->next_idx;
4015 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4017 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4018 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4019 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4020 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4021 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4025 while ((nested = mono_class_get_nested_types (klass, &iter)))
4026 add_exported_type (assemblyb, assembly, nested, current_idx);
4030 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4035 if (!assemblyb->type_forwarders)
4038 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4039 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4044 type = mono_reflection_type_get_handle (t);
4047 klass = mono_class_from_mono_type (type);
4049 add_exported_type (assemblyb, assembly, klass, 0);
4053 #define align_pointer(base,p)\
4055 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4057 (p) += 4 - (__diff & 3);\
4061 compare_constants (const void *a, const void *b)
4063 const guint32 *a_values = a;
4064 const guint32 *b_values = b;
4065 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4069 compare_semantics (const void *a, const void *b)
4071 const guint32 *a_values = a;
4072 const guint32 *b_values = b;
4073 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4076 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4080 compare_custom_attrs (const void *a, const void *b)
4082 const guint32 *a_values = a;
4083 const guint32 *b_values = b;
4085 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4089 compare_field_marshal (const void *a, const void *b)
4091 const guint32 *a_values = a;
4092 const guint32 *b_values = b;
4094 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4098 compare_nested (const void *a, const void *b)
4100 const guint32 *a_values = a;
4101 const guint32 *b_values = b;
4103 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4107 compare_genericparam (const void *a, const void *b)
4109 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4110 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4112 if ((*b_entry)->owner == (*a_entry)->owner)
4114 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4115 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4117 return (*a_entry)->owner - (*b_entry)->owner;
4121 compare_declsecurity_attrs (const void *a, const void *b)
4123 const guint32 *a_values = a;
4124 const guint32 *b_values = b;
4126 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4130 compare_interface_impl (const void *a, const void *b)
4132 const guint32 *a_values = a;
4133 const guint32 *b_values = b;
4135 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4139 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4143 pad_heap (MonoDynamicStream *sh)
4145 if (sh->index & 3) {
4146 int sz = 4 - (sh->index & 3);
4147 memset (sh->data + sh->index, 0, sz);
4154 MonoDynamicStream *stream;
4158 * build_compressed_metadata() fills in the blob of data that represents the
4159 * raw metadata as it will be saved in the PE file. The five streams are output
4160 * and the metadata tables are comnpressed from the guint32 array representation,
4161 * to the compressed on-disk format.
4164 build_compressed_metadata (MonoDynamicImage *assembly)
4166 MonoDynamicTable *table;
4168 guint64 valid_mask = 0;
4169 guint64 sorted_mask;
4170 guint32 heapt_size = 0;
4171 guint32 meta_size = 256; /* allow for header and other stuff */
4172 guint32 table_offset;
4173 guint32 ntables = 0;
4179 struct StreamDesc stream_desc [5];
4181 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4182 for (i = 0; i < assembly->gen_params->len; i++){
4183 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4184 write_generic_param_entry (assembly, entry);
4187 stream_desc [0].name = "#~";
4188 stream_desc [0].stream = &assembly->tstream;
4189 stream_desc [1].name = "#Strings";
4190 stream_desc [1].stream = &assembly->sheap;
4191 stream_desc [2].name = "#US";
4192 stream_desc [2].stream = &assembly->us;
4193 stream_desc [3].name = "#Blob";
4194 stream_desc [3].stream = &assembly->blob;
4195 stream_desc [4].name = "#GUID";
4196 stream_desc [4].stream = &assembly->guid;
4198 /* tables that are sorted */
4199 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4200 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4201 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4202 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4203 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4204 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4205 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4207 /* Compute table sizes */
4208 /* the MonoImage has already been created in mono_image_basic_init() */
4209 meta = &assembly->image;
4211 /* sizes should be multiple of 4 */
4212 pad_heap (&assembly->blob);
4213 pad_heap (&assembly->guid);
4214 pad_heap (&assembly->sheap);
4215 pad_heap (&assembly->us);
4217 /* Setup the info used by compute_sizes () */
4218 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4219 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4220 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4222 meta_size += assembly->blob.index;
4223 meta_size += assembly->guid.index;
4224 meta_size += assembly->sheap.index;
4225 meta_size += assembly->us.index;
4227 for (i=0; i < MONO_TABLE_NUM; ++i)
4228 meta->tables [i].rows = assembly->tables [i].rows;
4230 for (i = 0; i < MONO_TABLE_NUM; i++){
4231 if (meta->tables [i].rows == 0)
4233 valid_mask |= (guint64)1 << i;
4235 meta->tables [i].row_size = mono_metadata_compute_size (
4236 meta, i, &meta->tables [i].size_bitfield);
4237 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4239 heapt_size += 24; /* #~ header size */
4240 heapt_size += ntables * 4;
4241 /* make multiple of 4 */
4244 meta_size += heapt_size;
4245 meta->raw_metadata = g_malloc0 (meta_size);
4246 p = (unsigned char*)meta->raw_metadata;
4247 /* the metadata signature */
4248 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4249 /* version numbers and 4 bytes reserved */
4250 int16val = (guint16*)p;
4251 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4252 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4254 /* version string */
4255 int32val = (guint32*)p;
4256 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4258 memcpy (p, meta->version, strlen (meta->version));
4259 p += GUINT32_FROM_LE (*int32val);
4260 align_pointer (meta->raw_metadata, p);
4261 int16val = (guint16*)p;
4262 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4263 *int16val = GUINT16_TO_LE (5); /* number of streams */
4267 * write the stream info.
4269 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4270 table_offset += 3; table_offset &= ~3;
4272 assembly->tstream.index = heapt_size;
4273 for (i = 0; i < 5; ++i) {
4274 int32val = (guint32*)p;
4275 stream_desc [i].stream->offset = table_offset;
4276 *int32val++ = GUINT32_TO_LE (table_offset);
4277 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4278 table_offset += GUINT32_FROM_LE (*int32val);
4279 table_offset += 3; table_offset &= ~3;
4281 strcpy ((char*)p, stream_desc [i].name);
4282 p += strlen (stream_desc [i].name) + 1;
4283 align_pointer (meta->raw_metadata, p);
4286 * now copy the data, the table stream header and contents goes first.
4288 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4289 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4290 int32val = (guint32*)p;
4291 *int32val = GUINT32_TO_LE (0); /* reserved */
4294 *p++ = 2; /* version */
4297 if (meta->idx_string_wide)
4299 if (meta->idx_guid_wide)
4301 if (meta->idx_blob_wide)
4304 *p++ = 1; /* reserved */
4305 int64val = (guint64*)p;
4306 *int64val++ = GUINT64_TO_LE (valid_mask);
4307 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4309 int32val = (guint32*)p;
4310 for (i = 0; i < MONO_TABLE_NUM; i++){
4311 if (meta->tables [i].rows == 0)
4313 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4315 p = (unsigned char*)int32val;
4317 /* sort the tables that still need sorting */
4318 table = &assembly->tables [MONO_TABLE_CONSTANT];
4320 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4321 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4323 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4324 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4326 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4327 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4329 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4330 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4332 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4333 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4334 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4336 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4337 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4339 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4341 /* compress the tables */
4342 for (i = 0; i < MONO_TABLE_NUM; i++){
4345 guint32 bitfield = meta->tables [i].size_bitfield;
4346 if (!meta->tables [i].rows)
4348 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4349 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4350 meta->tables [i].base = (char*)p;
4351 for (row = 1; row <= meta->tables [i].rows; ++row) {
4352 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4353 for (col = 0; col < assembly->tables [i].columns; ++col) {
4354 switch (mono_metadata_table_size (bitfield, col)) {
4356 *p++ = values [col];
4359 *p++ = values [col] & 0xff;
4360 *p++ = (values [col] >> 8) & 0xff;
4363 *p++ = values [col] & 0xff;
4364 *p++ = (values [col] >> 8) & 0xff;
4365 *p++ = (values [col] >> 16) & 0xff;
4366 *p++ = (values [col] >> 24) & 0xff;
4369 g_assert_not_reached ();
4373 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4376 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4377 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4378 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4379 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4380 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4382 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4386 * Some tables in metadata need to be sorted according to some criteria, but
4387 * when methods and fields are first created with reflection, they may be assigned a token
4388 * that doesn't correspond to the final token they will get assigned after the sorting.
4389 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4390 * with the reflection objects that represent them. Once all the tables are set up, the
4391 * reflection objects will contains the correct table index. fixup_method() will fixup the
4392 * tokens for the method with ILGenerator @ilgen.
4395 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4397 guint32 code_idx = GPOINTER_TO_UINT (value);
4398 MonoReflectionILTokenInfo *iltoken;
4399 MonoReflectionFieldBuilder *field;
4400 MonoReflectionCtorBuilder *ctor;
4401 MonoReflectionMethodBuilder *method;
4402 MonoReflectionTypeBuilder *tb;
4403 MonoReflectionArrayMethod *am;
4405 unsigned char *target;
4407 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4408 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4409 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4410 switch (target [3]) {
4411 case MONO_TABLE_FIELD:
4412 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4413 field = (MonoReflectionFieldBuilder *)iltoken->member;
4414 idx = field->table_idx;
4415 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4416 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4417 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4419 g_assert_not_reached ();
4422 case MONO_TABLE_METHOD:
4423 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4424 method = (MonoReflectionMethodBuilder *)iltoken->member;
4425 idx = method->table_idx;
4426 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4427 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4428 idx = ctor->table_idx;
4429 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4430 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4431 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4432 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4434 g_assert_not_reached ();
4437 case MONO_TABLE_TYPEDEF:
4438 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4439 g_assert_not_reached ();
4440 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4441 idx = tb->table_idx;
4443 case MONO_TABLE_MEMBERREF:
4444 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4445 am = (MonoReflectionArrayMethod*)iltoken->member;
4446 idx = am->table_idx;
4447 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4448 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4449 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4450 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4451 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4452 g_assert (m->klass->generic_class || m->klass->generic_container);
4454 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4456 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4457 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4458 g_assert (is_field_on_inst (f));
4460 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4461 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4463 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4465 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4467 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4470 g_assert_not_reached ();
4473 case MONO_TABLE_METHODSPEC:
4474 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4475 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4476 g_assert (mono_method_signature (m)->generic_param_count);
4478 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4480 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4483 g_assert_not_reached ();
4487 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4489 target [0] = idx & 0xff;
4490 target [1] = (idx >> 8) & 0xff;
4491 target [2] = (idx >> 16) & 0xff;
4498 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4499 * value is not known when the table is emitted.
4502 fixup_cattrs (MonoDynamicImage *assembly)
4504 MonoDynamicTable *table;
4506 guint32 type, i, idx, token;
4509 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4511 for (i = 0; i < table->rows; ++i) {
4512 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4514 type = values [MONO_CUSTOM_ATTR_TYPE];
4515 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4516 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4517 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4518 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4521 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4522 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4523 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4524 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4525 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4526 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4527 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4528 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4535 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4537 MonoDynamicTable *table;
4540 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4542 alloc_table (table, table->rows);
4543 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4544 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4545 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4546 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4547 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4552 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4554 MonoDynamicTable *table;
4558 char *b = blob_size;
4560 guint32 idx, offset;
4562 if (rsrc->filename) {
4563 name = mono_string_to_utf8 (rsrc->filename);
4564 sname = g_path_get_basename (name);
4566 table = &assembly->tables [MONO_TABLE_FILE];
4568 alloc_table (table, table->rows);
4569 values = table->values + table->next_idx * MONO_FILE_SIZE;
4570 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4571 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4574 mono_sha1_get_digest_from_file (name, hash);
4575 mono_metadata_encode_value (20, b, &b);
4576 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4577 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4579 idx = table->next_idx++;
4581 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4587 data = mono_array_addr (rsrc->data, char, 0);
4588 len = mono_array_length (rsrc->data);
4594 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4595 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4596 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4597 mono_image_add_stream_data (&assembly->resources, data, len);
4601 * The entry should be emitted into the MANIFESTRESOURCE table of
4602 * the main module, but that needs to reference the FILE table
4603 * which isn't emitted yet.
4610 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4614 set_version_from_string (MonoString *version, guint32 *values)
4616 gchar *ver, *p, *str;
4619 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4620 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4621 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4622 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4625 ver = str = mono_string_to_utf8 (version);
4626 for (i = 0; i < 4; ++i) {
4627 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4633 /* handle Revision and Build */
4643 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4647 char *b = blob_size;
4652 len = mono_array_length (pkey);
4653 mono_metadata_encode_value (len, b, &b);
4654 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4655 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4657 assembly->public_key = g_malloc (len);
4658 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4659 assembly->public_key_len = len;
4661 /* Special case: check for ECMA key (16 bytes) */
4662 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4663 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4664 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4665 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4666 /* minimum key size (in 2.0) is 384 bits */
4667 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4669 /* FIXME - verifier */
4670 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4671 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4673 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4679 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4681 MonoDynamicTable *table;
4682 MonoDynamicImage *assembly;
4683 MonoReflectionAssemblyBuilder *assemblyb;
4687 guint32 module_index;
4689 assemblyb = moduleb->assemblyb;
4690 assembly = moduleb->dynamic_image;
4691 domain = mono_object_domain (assemblyb);
4693 /* Emit ASSEMBLY table */
4694 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4695 alloc_table (table, 1);
4696 values = table->values + MONO_ASSEMBLY_SIZE;
4697 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4698 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4699 if (assemblyb->culture) {
4700 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4702 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4704 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4705 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4706 set_version_from_string (assemblyb->version, values);
4708 /* Emit FILE + EXPORTED_TYPE table */
4710 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4712 MonoReflectionModuleBuilder *file_module =
4713 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4714 if (file_module != moduleb) {
4715 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4717 if (file_module->types) {
4718 for (j = 0; j < file_module->num_types; ++j) {
4719 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4720 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4725 if (assemblyb->loaded_modules) {
4726 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4727 MonoReflectionModule *file_module =
4728 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4729 mono_image_fill_file_table (domain, file_module, assembly);
4731 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4734 if (assemblyb->type_forwarders)
4735 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4737 /* Emit MANIFESTRESOURCE table */
4739 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4741 MonoReflectionModuleBuilder *file_module =
4742 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4743 /* The table for the main module is emitted later */
4744 if (file_module != moduleb) {
4746 if (file_module->resources) {
4747 int len = mono_array_length (file_module->resources);
4748 for (j = 0; j < len; ++j) {
4749 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4750 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4757 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4760 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4761 * for the modulebuilder @moduleb.
4762 * At the end of the process, method and field tokens are fixed up and the
4763 * on-disk compressed metadata representation is created.
4766 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4768 MonoDynamicTable *table;
4769 MonoDynamicImage *assembly;
4770 MonoReflectionAssemblyBuilder *assemblyb;
4776 assemblyb = moduleb->assemblyb;
4777 assembly = moduleb->dynamic_image;
4778 domain = mono_object_domain (assemblyb);
4780 if (assembly->text_rva)
4783 assembly->text_rva = START_TEXT_RVA;
4785 if (moduleb->is_main) {
4786 mono_image_emit_manifest (moduleb);
4789 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4790 table->rows = 1; /* .<Module> */
4792 alloc_table (table, table->rows);
4794 * Set the first entry.
4796 values = table->values + table->columns;
4797 values [MONO_TYPEDEF_FLAGS] = 0;
4798 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4799 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4800 values [MONO_TYPEDEF_EXTENDS] = 0;
4801 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4802 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4805 * handle global methods
4806 * FIXME: test what to do when global methods are defined in multiple modules.
4808 if (moduleb->global_methods) {
4809 table = &assembly->tables [MONO_TABLE_METHOD];
4810 table->rows += mono_array_length (moduleb->global_methods);
4811 alloc_table (table, table->rows);
4812 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4813 mono_image_get_method_info (
4814 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4816 if (moduleb->global_fields) {
4817 table = &assembly->tables [MONO_TABLE_FIELD];
4818 table->rows += mono_array_length (moduleb->global_fields);
4819 alloc_table (table, table->rows);
4820 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4821 mono_image_get_field_info (
4822 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4825 table = &assembly->tables [MONO_TABLE_MODULE];
4826 alloc_table (table, 1);
4827 mono_image_fill_module_table (domain, moduleb, assembly);
4829 /* Collect all types into a list sorted by their table_idx */
4830 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4833 for (i = 0; i < moduleb->num_types; ++i) {
4834 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4835 collect_types (&types, type);
4838 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840 table->rows += mono_ptr_array_size (types);
4841 alloc_table (table, table->rows);
4844 * Emit type names + namespaces at one place inside the string heap,
4845 * so load_class_names () needs to touch fewer pages.
4847 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4848 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4849 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4851 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4852 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4853 string_heap_insert_mstring (&assembly->sheap, tb->name);
4856 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4857 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4858 mono_image_get_type_info (domain, type, assembly);
4862 * table->rows is already set above and in mono_image_fill_module_table.
4864 /* add all the custom attributes at the end, once all the indexes are stable */
4865 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4867 /* CAS assembly permissions */
4868 if (assemblyb->permissions_minimum)
4869 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4870 if (assemblyb->permissions_optional)
4871 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4872 if (assemblyb->permissions_refused)
4873 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4875 module_add_cattrs (assembly, moduleb);
4878 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4880 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4881 * the final tokens and don't need another fixup pass. */
4883 if (moduleb->global_methods) {
4884 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4885 MonoReflectionMethodBuilder *mb = mono_array_get (
4886 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4887 mono_image_add_methodimpl (assembly, mb);
4891 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4892 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4893 if (type->methods) {
4894 for (j = 0; j < type->num_methods; ++j) {
4895 MonoReflectionMethodBuilder *mb = mono_array_get (
4896 type->methods, MonoReflectionMethodBuilder*, j);
4898 mono_image_add_methodimpl (assembly, mb);
4903 mono_ptr_array_destroy (types);
4905 fixup_cattrs (assembly);
4908 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4911 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4913 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4916 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4920 guint32 import_lookup_table;
4924 guint32 import_address_table_rva;
4932 #ifndef DISABLE_REFLECTION_EMIT
4935 * mono_image_insert_string:
4936 * @module: module builder object
4939 * Insert @str into the user string stream of @module.
4942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4944 MonoDynamicImage *assembly;
4949 if (!module->dynamic_image)
4950 mono_image_module_basic_init (module);
4952 assembly = module->dynamic_image;
4954 if (assembly->save) {
4955 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4956 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4957 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4959 char *swapped = g_malloc (2 * mono_string_length (str));
4960 const char *p = (const char*)mono_string_chars (str);
4962 swap_with_size (swapped, p, 2, mono_string_length (str));
4963 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4967 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4969 mono_image_add_stream_data (&assembly->us, "", 1);
4971 idx = assembly->us.index ++;
4974 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4976 return MONO_TOKEN_STRING | idx;
4980 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4984 MonoMethodSignature *sig;
4986 klass = obj->vtable->klass;
4987 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4988 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4989 MonoMethodSignature *old;
4990 guint32 sig_token, parent;
4993 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4995 nargs = mono_array_length (opt_param_types);
4996 old = mono_method_signature (method);
4997 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4999 sig->hasthis = old->hasthis;
5000 sig->explicit_this = old->explicit_this;
5001 sig->call_convention = old->call_convention;
5002 sig->generic_param_count = old->generic_param_count;
5003 sig->param_count = old->param_count + nargs;
5004 sig->sentinelpos = old->param_count;
5005 sig->ret = old->ret;
5007 for (i = 0; i < old->param_count; i++)
5008 sig->params [i] = old->params [i];
5010 for (i = 0; i < nargs; i++) {
5011 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5012 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5015 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5016 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5017 parent >>= MONO_TYPEDEFORREF_BITS;
5019 parent <<= MONO_MEMBERREF_PARENT_BITS;
5020 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5022 sig_token = method_encode_signature (assembly, sig);
5023 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5024 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5025 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5026 ReflectionMethodBuilder rmb;
5027 guint32 parent, sig_token;
5028 int nopt_args, nparams, ngparams, i;
5031 reflection_methodbuilder_from_method_builder (&rmb, mb);
5032 rmb.opt_types = opt_param_types;
5033 nopt_args = mono_array_length (opt_param_types);
5035 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5036 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5037 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5039 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5040 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5041 sig->call_convention = rmb.call_conv;
5042 sig->generic_param_count = ngparams;
5043 sig->param_count = nparams + nopt_args;
5044 sig->sentinelpos = nparams;
5045 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5047 for (i = 0; i < nparams; i++) {
5048 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5049 sig->params [i] = mono_reflection_type_get_handle (rt);
5052 for (i = 0; i < nopt_args; i++) {
5053 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5057 sig_token = method_builder_encode_signature (assembly, &rmb);
5059 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5060 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5062 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5063 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5065 name = mono_string_to_utf8 (rmb.name);
5066 token = mono_image_get_varargs_method_token (
5067 assembly, parent, name, sig_token);
5070 g_error ("requested method token for %s\n", klass->name);
5073 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5074 register_dyn_token (assembly, token, obj);
5079 * mono_image_create_token:
5080 * @assembly: a dynamic assembly
5082 * @register_token: Whenever to register the token in the assembly->tokens hash.
5084 * Get a token to insert in the IL code stream for the given MemberInfo.
5085 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5086 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5090 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5091 gboolean create_open_instance, gboolean register_token)
5096 klass = obj->vtable->klass;
5098 /* Check for user defined reflection objects */
5099 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5100 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5101 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5103 if (strcmp (klass->name, "MethodBuilder") == 0) {
5104 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5105 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5107 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5108 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5110 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5111 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5112 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5113 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5114 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5116 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5117 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5119 token = mono_image_get_ctorbuilder_token (assembly, mb);
5120 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5121 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5122 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5123 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5124 if (tb->generic_params) {
5125 token = mono_image_get_generic_field_token (assembly, fb);
5127 if (tb->module->dynamic_image == assembly) {
5128 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5130 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5133 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5134 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5135 if (create_open_instance && tb->generic_params) {
5137 init_type_builder_generics (obj);
5138 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5139 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5140 token = mono_metadata_token_from_dor (token);
5141 } else if (tb->module->dynamic_image == assembly) {
5142 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5145 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5146 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5148 } else if (strcmp (klass->name, "MonoType") == 0) {
5149 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5150 MonoClass *mc = mono_class_from_mono_type (type);
5151 token = mono_metadata_token_from_dor (
5152 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5153 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5154 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5155 token = mono_metadata_token_from_dor (
5156 mono_image_typedef_or_ref (assembly, type));
5157 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5158 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5159 token = mono_metadata_token_from_dor (
5160 mono_image_typedef_or_ref (assembly, type));
5161 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5162 strcmp (klass->name, "MonoMethod") == 0 ||
5163 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5164 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5165 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5166 if (m->method->is_inflated) {
5167 if (create_open_instance)
5168 token = mono_image_get_methodspec_token (assembly, m->method);
5170 token = mono_image_get_inflated_method_token (assembly, m->method);
5171 } else if ((m->method->klass->image == &assembly->image) &&
5172 !m->method->klass->generic_class) {
5173 static guint32 method_table_idx = 0xffffff;
5174 if (m->method->klass->wastypebuilder) {
5175 /* we use the same token as the one that was assigned
5176 * to the Methodbuilder.
5177 * FIXME: do the equivalent for Fields.
5179 token = m->method->token;
5182 * Each token should have a unique index, but the indexes are
5183 * assigned by managed code, so we don't know about them. An
5184 * easy solution is to count backwards...
5186 method_table_idx --;
5187 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5190 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5192 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5193 } else if (strcmp (klass->name, "MonoField") == 0) {
5194 MonoReflectionField *f = (MonoReflectionField *)obj;
5195 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5196 static guint32 field_table_idx = 0xffffff;
5198 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5200 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5202 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5203 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5204 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5205 token = mono_image_get_array_token (assembly, m);
5206 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5207 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5208 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5209 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5210 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5211 token = mono_metadata_token_from_dor (
5212 mono_image_typedef_or_ref (assembly, type));
5213 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5214 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5215 token = mono_image_get_field_on_inst_token (assembly, f);
5216 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5217 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5218 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5219 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5220 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5221 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5222 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5223 MonoReflectionType *type = (MonoReflectionType *)obj;
5224 token = mono_metadata_token_from_dor (
5225 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5227 g_error ("requested token for %s\n", klass->name);
5231 mono_image_register_token (assembly, token, obj);
5237 * mono_image_register_token:
5239 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5240 * the Module.ResolveXXXToken () methods to work.
5243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5247 dynamic_image_lock (assembly);
5248 prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5250 /* There could be multiple MethodInfo objects with the same token */
5251 //g_assert (prev == obj);
5253 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5255 dynamic_image_unlock (assembly);
5258 static MonoDynamicImage*
5259 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5261 static const guchar entrycode [16] = {0xff, 0x25, 0};
5262 MonoDynamicImage *image;
5265 const char *version;
5267 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5268 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5270 version = mono_get_runtime_info ()->runtime_version;
5273 /* The MonoGHashTable's need GC tracking */
5274 image = GC_MALLOC (sizeof (MonoDynamicImage));
5276 image = g_new0 (MonoDynamicImage, 1);
5279 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5281 /*g_print ("created image %p\n", image);*/
5282 /* keep in sync with image.c */
5283 image->image.name = assembly_name;
5284 image->image.assembly_name = image->image.name; /* they may be different */
5285 image->image.module_name = module_name;
5286 image->image.version = g_strdup (version);
5287 image->image.md_version_major = 1;
5288 image->image.md_version_minor = 1;
5289 image->image.dynamic = TRUE;
5291 image->image.references = g_new0 (MonoAssembly*, 1);
5292 image->image.references [0] = NULL;
5294 mono_image_init (&image->image);
5296 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5297 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5298 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5299 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5300 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5301 image->handleref = g_hash_table_new (NULL, NULL);
5302 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5303 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5304 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5305 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5306 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5307 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5308 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5309 image->gen_params = g_ptr_array_new ();
5310 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5312 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5313 string_heap_init (&image->sheap);
5314 mono_image_add_stream_data (&image->us, "", 1);
5315 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5316 /* import tables... */
5317 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5318 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5319 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5320 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5321 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5322 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5323 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5324 stream_data_align (&image->code);
5326 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5328 for (i=0; i < MONO_TABLE_NUM; ++i) {
5329 image->tables [i].next_idx = 1;
5330 image->tables [i].columns = table_sizes [i];
5333 image->image.assembly = (MonoAssembly*)assembly;
5334 image->run = assembly->run;
5335 image->save = assembly->save;
5336 image->pe_kind = 0x1; /* ILOnly */
5337 image->machine = 0x14c; /* I386 */
5339 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5346 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5352 release_hashtable (MonoGHashTable **hash)
5355 mono_g_hash_table_destroy (*hash);
5361 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5363 release_hashtable (&image->token_fixups);
5364 release_hashtable (&image->handleref_managed);
5365 release_hashtable (&image->tokens);
5366 release_hashtable (&image->remapped_tokens);
5367 release_hashtable (&image->generic_def_objects);
5368 release_hashtable (&image->methodspec);
5372 mono_dynamic_image_free (MonoDynamicImage *image)
5374 MonoDynamicImage *di = image;
5379 mono_g_hash_table_destroy (di->methodspec);
5381 g_hash_table_destroy (di->typespec);
5383 g_hash_table_destroy (di->typeref);
5385 g_hash_table_destroy (di->handleref);
5386 if (di->handleref_managed)
5387 mono_g_hash_table_destroy (di->handleref_managed);
5389 mono_g_hash_table_destroy (di->tokens);
5390 if (di->remapped_tokens)
5391 mono_g_hash_table_destroy (di->remapped_tokens);
5392 if (di->generic_def_objects)
5393 mono_g_hash_table_destroy (di->generic_def_objects);
5394 if (di->blob_cache) {
5395 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5396 g_hash_table_destroy (di->blob_cache);
5398 if (di->standalonesig_cache)
5399 g_hash_table_destroy (di->standalonesig_cache);
5400 for (list = di->array_methods; list; list = list->next) {
5401 ArrayMethod *am = (ArrayMethod *)list->data;
5406 g_list_free (di->array_methods);
5407 if (di->gen_params) {
5408 for (i = 0; i < di->gen_params->len; i++) {
5409 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5410 mono_gc_deregister_root ((char*) &entry->gparam);
5413 g_ptr_array_free (di->gen_params, TRUE);
5415 if (di->token_fixups)
5416 mono_g_hash_table_destroy (di->token_fixups);
5417 if (di->method_to_table_idx)
5418 g_hash_table_destroy (di->method_to_table_idx);
5419 if (di->field_to_table_idx)
5420 g_hash_table_destroy (di->field_to_table_idx);
5421 if (di->method_aux_hash)
5422 g_hash_table_destroy (di->method_aux_hash);
5423 if (di->vararg_aux_hash)
5424 g_hash_table_destroy (di->vararg_aux_hash);
5425 g_free (di->strong_name);
5426 g_free (di->win32_res);
5428 g_free (di->public_key);
5430 /*g_print ("string heap destroy for image %p\n", di);*/
5431 mono_dynamic_stream_reset (&di->sheap);
5432 mono_dynamic_stream_reset (&di->code);
5433 mono_dynamic_stream_reset (&di->resources);
5434 mono_dynamic_stream_reset (&di->us);
5435 mono_dynamic_stream_reset (&di->blob);
5436 mono_dynamic_stream_reset (&di->tstream);
5437 mono_dynamic_stream_reset (&di->guid);
5438 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5439 g_free (di->tables [i].values);
5444 mono_dynamic_image_free_image (MonoDynamicImage *image)
5446 /* See create_dynamic_mono_image () */
5448 /* Allocated using GC_MALLOC */
5454 #ifndef DISABLE_REFLECTION_EMIT
5457 * mono_image_basic_init:
5458 * @assembly: an assembly builder object
5460 * Create the MonoImage that represents the assembly builder and setup some
5461 * of the helper hash table and the basic metadata streams.
5464 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5466 MonoDynamicAssembly *assembly;
5467 MonoDynamicImage *image;
5468 MonoDomain *domain = mono_object_domain (assemblyb);
5470 if (assemblyb->dynamic_assembly)
5474 /* assembly->assembly.image might be GC allocated */
5475 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5477 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5480 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5482 assembly->assembly.ref_count = 1;
5483 assembly->assembly.dynamic = TRUE;
5484 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5485 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5486 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5487 if (assemblyb->culture)
5488 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5490 assembly->assembly.aname.culture = g_strdup ("");
5492 if (assemblyb->version) {
5493 char *vstr = mono_string_to_utf8 (assemblyb->version);
5494 char **version = g_strsplit (vstr, ".", 4);
5495 char **parts = version;
5496 assembly->assembly.aname.major = atoi (*parts++);
5497 assembly->assembly.aname.minor = atoi (*parts++);
5498 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5499 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5501 g_strfreev (version);
5504 assembly->assembly.aname.major = 0;
5505 assembly->assembly.aname.minor = 0;
5506 assembly->assembly.aname.build = 0;
5507 assembly->assembly.aname.revision = 0;
5510 assembly->run = assemblyb->access != 2;
5511 assembly->save = assemblyb->access != 1;
5512 assembly->domain = domain;
5514 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5515 image->initial_image = TRUE;
5516 assembly->assembly.aname.name = image->image.name;
5517 assembly->assembly.image = &image->image;
5518 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5519 /* -1 to correct for the trailing NULL byte */
5520 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5521 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5523 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5526 mono_domain_assemblies_lock (domain);
5527 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5528 mono_domain_assemblies_unlock (domain);
5530 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5532 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5534 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5537 #endif /* !DISABLE_REFLECTION_EMIT */
5539 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5542 calc_section_size (MonoDynamicImage *assembly)
5546 /* alignment constraints */
5547 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5548 g_assert ((assembly->code.index % 4) == 0);
5549 assembly->meta_size += 3;
5550 assembly->meta_size &= ~3;
5551 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5552 g_assert ((assembly->resources.index % 4) == 0);
5554 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5555 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5558 if (assembly->win32_res) {
5559 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5561 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5562 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5566 assembly->sections [MONO_SECTION_RELOC].size = 12;
5567 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5577 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5581 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5583 ResTreeNode *t1 = (ResTreeNode*)a;
5584 ResTreeNode *t2 = (ResTreeNode*)b;
5586 return t1->id - t2->id;
5590 * resource_tree_create:
5592 * Organize the resources into a resource tree.
5594 static ResTreeNode *
5595 resource_tree_create (MonoArray *win32_resources)
5597 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5601 tree = g_new0 (ResTreeNode, 1);
5603 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5604 MonoReflectionWin32Resource *win32_res =
5605 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5609 /* FIXME: BUG: this stores managed references in unmanaged memory */
5610 lang_node = g_new0 (ResTreeNode, 1);
5611 lang_node->id = win32_res->lang_id;
5612 lang_node->win32_res = win32_res;
5614 /* Create type node if neccesary */
5616 for (l = tree->children; l; l = l->next)
5617 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5618 type_node = (ResTreeNode*)l->data;
5623 type_node = g_new0 (ResTreeNode, 1);
5624 type_node->id = win32_res->res_type;
5627 * The resource types have to be sorted otherwise
5628 * Windows Explorer can't display the version information.
5630 tree->children = g_slist_insert_sorted (tree->children,
5631 type_node, resource_tree_compare_by_id);
5634 /* Create res node if neccesary */
5636 for (l = type_node->children; l; l = l->next)
5637 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5638 res_node = (ResTreeNode*)l->data;
5643 res_node = g_new0 (ResTreeNode, 1);
5644 res_node->id = win32_res->res_id;
5645 type_node->children = g_slist_append (type_node->children, res_node);
5648 res_node->children = g_slist_append (res_node->children, lang_node);
5655 * resource_tree_encode:
5657 * Encode the resource tree into the format used in the PE file.
5660 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5663 MonoPEResourceDir dir;
5664 MonoPEResourceDirEntry dir_entry;
5665 MonoPEResourceDataEntry data_entry;
5667 guint32 res_id_entries;
5670 * For the format of the resource directory, see the article
5671 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5675 memset (&dir, 0, sizeof (dir));
5676 memset (&dir_entry, 0, sizeof (dir_entry));
5677 memset (&data_entry, 0, sizeof (data_entry));
5679 g_assert (sizeof (dir) == 16);
5680 g_assert (sizeof (dir_entry) == 8);
5681 g_assert (sizeof (data_entry) == 16);
5683 node->offset = p - begin;
5685 /* IMAGE_RESOURCE_DIRECTORY */
5686 res_id_entries = g_slist_length (node->children);
5687 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5689 memcpy (p, &dir, sizeof (dir));
5692 /* Reserve space for entries */
5694 p += sizeof (dir_entry) * res_id_entries;
5696 /* Write children */
5697 for (l = node->children; l; l = l->next) {
5698 ResTreeNode *child = (ResTreeNode*)l->data;
5700 if (child->win32_res) {
5703 child->offset = p - begin;
5705 /* IMAGE_RESOURCE_DATA_ENTRY */
5706 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5707 size = mono_array_length (child->win32_res->res_data);
5708 data_entry.rde_size = GUINT32_TO_LE (size);
5710 memcpy (p, &data_entry, sizeof (data_entry));
5711 p += sizeof (data_entry);
5713 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5716 resource_tree_encode (child, begin, p, &p);
5720 /* IMAGE_RESOURCE_ENTRY */
5721 for (l = node->children; l; l = l->next) {
5722 ResTreeNode *child = (ResTreeNode*)l->data;
5724 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5725 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5727 memcpy (entries, &dir_entry, sizeof (dir_entry));
5728 entries += sizeof (dir_entry);
5735 resource_tree_free (ResTreeNode * node)
5738 for (list = node->children; list; list = list->next)
5739 resource_tree_free ((ResTreeNode*)list->data);
5740 g_slist_free(node->children);
5745 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5750 MonoReflectionWin32Resource *win32_res;
5753 if (!assemblyb->win32_resources)
5757 * Resources are stored in a three level tree inside the PE file.
5758 * - level one contains a node for each type of resource
5759 * - level two contains a node for each resource
5760 * - level three contains a node for each instance of a resource for a
5761 * specific language.
5764 tree = resource_tree_create (assemblyb->win32_resources);
5766 /* Estimate the size of the encoded tree */
5768 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5769 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5770 size += mono_array_length (win32_res->res_data);
5772 /* Directory structure */
5773 size += mono_array_length (assemblyb->win32_resources) * 256;
5774 p = buf = g_malloc (size);
5776 resource_tree_encode (tree, p, p, &p);
5778 g_assert (p - buf <= size);
5780 assembly->win32_res = g_malloc (p - buf);
5781 assembly->win32_res_size = p - buf;
5782 memcpy (assembly->win32_res, buf, p - buf);
5785 resource_tree_free (tree);
5789 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5791 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5794 p += sizeof (MonoPEResourceDir);
5795 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5796 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5797 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5798 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5799 fixup_resource_directory (res_section, child, rva);
5801 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5802 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5805 p += sizeof (MonoPEResourceDirEntry);
5810 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5813 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5814 g_error ("WriteFile returned %d\n", GetLastError ());
5818 * mono_image_create_pefile:
5819 * @mb: a module builder object
5821 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5822 * assembly->pefile where it can be easily retrieved later in chunks.
5825 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5827 MonoMSDOSHeader *msdos;
5828 MonoDotNetHeader *header;
5829 MonoSectionTable *section;
5830 MonoCLIHeader *cli_header;
5831 guint32 size, image_size, virtual_base, text_offset;
5832 guint32 header_start, section_start, file_offset, virtual_offset;
5833 MonoDynamicImage *assembly;
5834 MonoReflectionAssemblyBuilder *assemblyb;
5835 MonoDynamicStream pefile_stream = {0};
5836 MonoDynamicStream *pefile = &pefile_stream;
5838 guint32 *rva, value;
5840 static const unsigned char msheader[] = {
5841 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5842 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5845 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5846 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5847 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5848 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5851 assemblyb = mb->assemblyb;
5853 mono_image_basic_init (assemblyb);
5854 assembly = mb->dynamic_image;
5856 assembly->pe_kind = assemblyb->pe_kind;
5857 assembly->machine = assemblyb->machine;
5858 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5859 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5861 mono_image_build_metadata (mb);
5863 if (mb->is_main && assemblyb->resources) {
5864 int len = mono_array_length (assemblyb->resources);
5865 for (i = 0; i < len; ++i)
5866 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5869 if (mb->resources) {
5870 int len = mono_array_length (mb->resources);
5871 for (i = 0; i < len; ++i)
5872 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5875 build_compressed_metadata (assembly);
5878 assembly_add_win32_resources (assembly, assemblyb);
5880 nsections = calc_section_size (assembly);
5882 /* The DOS header and stub */
5883 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5884 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5886 /* the dotnet header */
5887 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5889 /* the section tables */
5890 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5892 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5893 virtual_offset = VIRT_ALIGN;
5896 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897 if (!assembly->sections [i].size)
5900 file_offset += FILE_ALIGN - 1;
5901 file_offset &= ~(FILE_ALIGN - 1);
5902 virtual_offset += VIRT_ALIGN - 1;
5903 virtual_offset &= ~(VIRT_ALIGN - 1);
5905 assembly->sections [i].offset = file_offset;
5906 assembly->sections [i].rva = virtual_offset;
5908 file_offset += assembly->sections [i].size;
5909 virtual_offset += assembly->sections [i].size;
5910 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5913 file_offset += FILE_ALIGN - 1;
5914 file_offset &= ~(FILE_ALIGN - 1);
5916 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5918 /* back-patch info */
5919 msdos = (MonoMSDOSHeader*)pefile->data;
5920 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5922 header = (MonoDotNetHeader*)(pefile->data + header_start);
5923 header->pesig [0] = 'P';
5924 header->pesig [1] = 'E';
5926 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5927 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5928 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5929 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5930 if (assemblyb->pekind == 1) {
5932 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5935 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5938 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5940 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5941 header->pe.pe_major = 6;
5942 header->pe.pe_minor = 0;
5943 size = assembly->sections [MONO_SECTION_TEXT].size;
5944 size += FILE_ALIGN - 1;
5945 size &= ~(FILE_ALIGN - 1);
5946 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5947 size = assembly->sections [MONO_SECTION_RSRC].size;
5948 size += FILE_ALIGN - 1;
5949 size &= ~(FILE_ALIGN - 1);
5950 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5951 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5952 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5953 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5954 /* pe_rva_entry_point always at the beginning of the text section */
5955 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5957 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5958 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5959 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5960 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5961 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5962 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5963 size = section_start;
5964 size += FILE_ALIGN - 1;
5965 size &= ~(FILE_ALIGN - 1);
5966 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5968 size += VIRT_ALIGN - 1;
5969 size &= ~(VIRT_ALIGN - 1);
5970 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5973 // Translate the PEFileKind value to the value expected by the Windows loader
5979 // PEFileKinds.Dll == 1
5980 // PEFileKinds.ConsoleApplication == 2
5981 // PEFileKinds.WindowApplication == 3
5984 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5985 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5987 if (assemblyb->pekind == 3)
5992 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5994 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5995 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5996 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5997 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5998 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5999 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6001 /* fill data directory entries */
6003 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6004 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6006 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6007 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6009 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6010 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6011 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6012 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6013 /* patch entrypoint name */
6014 if (assemblyb->pekind == 1)
6015 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6017 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6018 /* patch imported function RVA name */
6019 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6020 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6022 /* the import table */
6023 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6024 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6025 /* patch imported dll RVA name and other entries in the dir */
6026 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6027 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6028 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6029 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6030 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6031 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6033 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6034 value = (assembly->text_rva + assembly->imp_names_offset);
6035 *p++ = (value) & 0xff;
6036 *p++ = (value >> 8) & (0xff);
6037 *p++ = (value >> 16) & (0xff);
6038 *p++ = (value >> 24) & (0xff);
6040 /* the CLI header info */
6041 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6042 cli_header->ch_size = GUINT32_FROM_LE (72);
6043 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6044 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6045 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6046 if (assemblyb->entry_point) {
6047 guint32 table_idx = 0;
6048 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6049 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6050 table_idx = methodb->table_idx;
6052 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6054 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6056 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6058 /* The embedded managed resources */
6059 text_offset = assembly->text_rva + assembly->code.index;
6060 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6061 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6062 text_offset += assembly->resources.index;
6063 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6064 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6065 text_offset += assembly->meta_size;
6066 if (assembly->strong_name_size) {
6067 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6068 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6069 text_offset += assembly->strong_name_size;
6072 /* write the section tables and section content */
6073 section = (MonoSectionTable*)(pefile->data + section_start);
6074 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6075 static const char section_names [][7] = {
6076 ".text", ".rsrc", ".reloc"
6078 if (!assembly->sections [i].size)
6080 strcpy (section->st_name, section_names [i]);
6081 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6082 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6083 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6084 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6085 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6086 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6087 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6091 checked_write_file (file, pefile->data, pefile->index);
6093 mono_dynamic_stream_reset (pefile);
6095 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6096 if (!assembly->sections [i].size)
6099 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6100 g_error ("SetFilePointer returned %d\n", GetLastError ());
6103 case MONO_SECTION_TEXT:
6104 /* patch entry point */
6105 p = (guchar*)(assembly->code.data + 2);
6106 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6107 *p++ = (value) & 0xff;
6108 *p++ = (value >> 8) & 0xff;
6109 *p++ = (value >> 16) & 0xff;
6110 *p++ = (value >> 24) & 0xff;
6112 checked_write_file (file, assembly->code.data, assembly->code.index);
6113 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6114 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6115 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6118 g_free (assembly->image.raw_metadata);
6120 case MONO_SECTION_RELOC: {
6124 guint16 type_and_offset;
6128 g_assert (sizeof (reloc) == 12);
6130 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6131 reloc.block_size = GUINT32_FROM_LE (12);
6134 * the entrypoint is always at the start of the text section
6135 * 3 is IMAGE_REL_BASED_HIGHLOW
6136 * 2 is patch_size_rva - text_rva
6138 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6141 checked_write_file (file, &reloc, sizeof (reloc));
6145 case MONO_SECTION_RSRC:
6146 if (assembly->win32_res) {
6148 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6149 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6150 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6154 g_assert_not_reached ();
6158 /* check that the file is properly padded */
6159 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160 g_error ("SetFilePointer returned %d\n", GetLastError ());
6161 if (! SetEndOfFile (file))
6162 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6164 mono_dynamic_stream_reset (&assembly->code);
6165 mono_dynamic_stream_reset (&assembly->us);
6166 mono_dynamic_stream_reset (&assembly->blob);
6167 mono_dynamic_stream_reset (&assembly->guid);
6168 mono_dynamic_stream_reset (&assembly->sheap);
6170 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6171 g_hash_table_destroy (assembly->blob_cache);
6172 assembly->blob_cache = NULL;
6175 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6178 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6180 g_assert_not_reached ();
6183 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6185 #ifndef DISABLE_REFLECTION_EMIT
6187 MonoReflectionModule *
6188 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6192 MonoImageOpenStatus status;
6193 MonoDynamicAssembly *assembly;
6194 guint32 module_count;
6195 MonoImage **new_modules;
6196 gboolean *new_modules_loaded;
6198 name = mono_string_to_utf8 (fileName);
6200 image = mono_image_open (name, &status);
6203 if (status == MONO_IMAGE_ERROR_ERRNO)
6204 exc = mono_get_exception_file_not_found (fileName);
6206 exc = mono_get_exception_bad_image_format (name);
6208 mono_raise_exception (exc);
6213 assembly = ab->dynamic_assembly;
6214 image->assembly = (MonoAssembly*)assembly;
6216 module_count = image->assembly->image->module_count;
6217 new_modules = g_new0 (MonoImage *, module_count + 1);
6218 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6220 if (image->assembly->image->modules)
6221 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6222 if (image->assembly->image->modules_loaded)
6223 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6224 new_modules [module_count] = image;
6225 new_modules_loaded [module_count] = TRUE;
6226 mono_image_addref (image);
6228 g_free (image->assembly->image->modules);
6229 image->assembly->image->modules = new_modules;
6230 image->assembly->image->modules_loaded = new_modules_loaded;
6231 image->assembly->image->module_count ++;
6233 mono_assembly_load_references (image, &status);
6235 mono_image_close (image);
6236 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6239 return mono_module_get_object (mono_domain_get (), image);
6242 #endif /* DISABLE_REFLECTION_EMIT */
6245 * We need to return always the same object for MethodInfo, FieldInfo etc..
6246 * but we need to consider the reflected type.
6247 * type uses a different hash, since it uses custom hash/equal functions.
6252 MonoClass *refclass;
6256 reflected_equal (gconstpointer a, gconstpointer b) {
6257 const ReflectedEntry *ea = a;
6258 const ReflectedEntry *eb = b;
6260 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6264 reflected_hash (gconstpointer a) {
6265 const ReflectedEntry *ea = a;
6266 return mono_aligned_addr_hash (ea->item);
6269 #define CHECK_OBJECT(t,p,k) \
6275 mono_domain_lock (domain); \
6276 if (!domain->refobject_hash) \
6277 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6278 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6279 mono_domain_unlock (domain); \
6282 mono_domain_unlock (domain); \
6285 #ifdef HAVE_BOEHM_GC
6286 /* ReflectedEntry doesn't need to be GC tracked */
6287 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6288 #define FREE_REFENTRY(entry) g_free ((entry))
6289 #define REFENTRY_REQUIRES_CLEANUP
6291 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6293 #define FREE_REFENTRY(entry)
6296 #define CACHE_OBJECT(t,p,o,k) \
6299 ReflectedEntry pe; \
6301 pe.refclass = (k); \
6302 mono_domain_lock (domain); \
6303 if (!domain->refobject_hash) \
6304 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6305 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6307 ReflectedEntry *e = ALLOC_REFENTRY; \
6309 e->refclass = (k); \
6310 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6313 mono_domain_unlock (domain); \
6318 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6320 mono_domain_lock (domain);
6321 if (domain->refobject_hash) {
6323 gpointer orig_pe, orig_value;
6326 pe.refclass = klass;
6327 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6328 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6329 FREE_REFENTRY (orig_pe);
6332 mono_domain_unlock (domain);
6335 #ifdef REFENTRY_REQUIRES_CLEANUP
6337 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6339 FREE_REFENTRY (key);
6344 mono_reflection_cleanup_domain (MonoDomain *domain)
6346 if (domain->refobject_hash) {
6347 /*let's avoid scanning the whole hashtable if not needed*/
6348 #ifdef REFENTRY_REQUIRES_CLEANUP
6349 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6351 mono_g_hash_table_destroy (domain->refobject_hash);
6352 domain->refobject_hash = NULL;
6356 #ifndef DISABLE_REFLECTION_EMIT
6358 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6360 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6364 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6366 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6370 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6372 MonoDynamicImage *image = moduleb->dynamic_image;
6373 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6377 MonoImage **new_modules;
6379 char *name, *fqname;
6381 * FIXME: we already created an image in mono_image_basic_init (), but
6382 * we don't know which module it belongs to, since that is only
6383 * determined at assembly save time.
6385 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6386 name = mono_string_to_utf8 (ab->name);
6387 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6388 if (!mono_error_ok (&error)) {
6390 mono_error_raise_exception (&error);
6392 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6394 moduleb->module.image = &image->image;
6395 moduleb->dynamic_image = image;
6396 register_module (mono_object_domain (moduleb), moduleb, image);
6398 /* register the module with the assembly */
6399 ass = ab->dynamic_assembly->assembly.image;
6400 module_count = ass->module_count;
6401 new_modules = g_new0 (MonoImage *, module_count + 1);
6404 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6405 new_modules [module_count] = &image->image;
6406 mono_image_addref (&image->image);
6408 g_free (ass->modules);
6409 ass->modules = new_modules;
6410 ass->module_count ++;
6415 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6417 MonoDynamicImage *image = moduleb->dynamic_image;
6419 g_assert (type->type);
6420 image->wrappers_type = mono_class_from_mono_type (type->type);
6426 * mono_assembly_get_object:
6427 * @domain: an app domain
6428 * @assembly: an assembly
6430 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6432 MonoReflectionAssembly*
6433 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6435 static MonoClass *assembly_type;
6436 MonoReflectionAssembly *res;
6438 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6439 if (!assembly_type) {
6440 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6442 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6444 assembly_type = class;
6446 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6447 res->assembly = assembly;
6449 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6454 MonoReflectionModule*
6455 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6457 static MonoClass *module_type;
6458 MonoReflectionModule *res;
6461 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6463 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6465 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6467 module_type = class;
6469 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6472 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6474 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6475 basename = g_path_get_basename (image->name);
6476 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6477 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6481 if (image->assembly->image == image) {
6482 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6486 if (image->assembly->image->modules) {
6487 for (i = 0; i < image->assembly->image->module_count; i++) {
6488 if (image->assembly->image->modules [i] == image)
6489 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6491 g_assert (res->token);
6495 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6498 MonoReflectionModule*
6499 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6501 static MonoClass *module_type;
6502 MonoReflectionModule *res;
6503 MonoTableInfo *table;
6504 guint32 cols [MONO_FILE_SIZE];
6506 guint32 i, name_idx;
6510 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6512 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6514 module_type = class;
6516 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6518 table = &image->tables [MONO_TABLE_FILE];
6519 g_assert (table_index < table->rows);
6520 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6523 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6524 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6526 /* Check whenever the row has a corresponding row in the moduleref table */
6527 table = &image->tables [MONO_TABLE_MODULEREF];
6528 for (i = 0; i < table->rows; ++i) {
6529 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6530 val = mono_metadata_string_heap (image, name_idx);
6531 if (strcmp (val, name) == 0)
6532 res->image = image->modules [i];
6535 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6536 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6537 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6538 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6539 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6545 verify_safe_for_managed_space (MonoType *type)
6547 switch (type->type) {
6549 case MONO_TYPE_ARRAY:
6550 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6552 return verify_safe_for_managed_space (type->data.type);
6553 case MONO_TYPE_SZARRAY:
6554 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6555 case MONO_TYPE_GENERICINST: {
6556 MonoGenericInst *inst = type->data.generic_class->inst;
6560 for (i = 0; i < inst->type_argc; ++i)
6561 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6567 case MONO_TYPE_MVAR:
6575 mono_type_normalize (MonoType *type)
6578 MonoGenericClass *gclass;
6579 MonoGenericInst *ginst;
6581 MonoGenericContainer *gcontainer;
6582 MonoType **argv = NULL;
6583 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6585 if (type->type != MONO_TYPE_GENERICINST)
6588 gclass = type->data.generic_class;
6589 ginst = gclass->context.class_inst;
6590 if (!ginst->is_open)
6593 gtd = gclass->container_class;
6594 gcontainer = gtd->generic_container;
6595 argv = g_newa (MonoType*, ginst->type_argc);
6597 for (i = 0; i < ginst->type_argc; ++i) {
6598 MonoType *t = ginst->type_argv [i], *norm;
6599 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6600 is_denorm_gtd = FALSE;
6601 norm = mono_type_normalize (t);
6604 requires_rebind = TRUE;
6608 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6610 if (requires_rebind) {
6611 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6612 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6618 * mono_type_get_object:
6619 * @domain: an app domain
6622 * Return an System.MonoType object representing the type @type.
6625 mono_type_get_object (MonoDomain *domain, MonoType *type)
6627 MonoType *norm_type;
6628 MonoReflectionType *res;
6629 MonoClass *klass = mono_class_from_mono_type (type);
6631 /*we must avoid using @type as it might have come
6632 * from a mono_metadata_type_dup and the caller
6633 * expects that is can be freed.
6634 * Using the right type from
6636 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6638 /* void is very common */
6639 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6640 return (MonoReflectionType*)domain->typeof_void;
6643 * If the vtable of the given class was already created, we can use
6644 * the MonoType from there and avoid all locking and hash table lookups.
6646 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6647 * that the resulting object is different.
6649 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6650 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6651 if (vtable && vtable->type)
6652 return vtable->type;
6655 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6656 mono_domain_lock (domain);
6657 if (!domain->type_hash)
6658 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6659 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6660 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6661 mono_domain_unlock (domain);
6662 mono_loader_unlock ();
6666 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6667 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6668 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6669 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6670 * artifact of how generics are encoded and should be transparent to managed code so we
6671 * need to weed out this diference when retrieving managed System.Type objects.
6673 norm_type = mono_type_normalize (type);
6674 if (norm_type != type) {
6675 res = mono_type_get_object (domain, norm_type);
6676 mono_g_hash_table_insert (domain->type_hash, type, res);
6677 mono_domain_unlock (domain);
6678 mono_loader_unlock ();
6682 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6683 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6686 if (!verify_safe_for_managed_space (type)) {
6687 mono_domain_unlock (domain);
6688 mono_loader_unlock ();
6689 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6692 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6693 gboolean is_type_done = TRUE;
6694 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6695 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6696 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6698 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6699 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6701 if (gparam->owner && gparam->owner->is_method) {
6702 MonoMethod *method = gparam->owner->owner.method;
6703 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6704 is_type_done = FALSE;
6705 } else if (gparam->owner && !gparam->owner->is_method) {
6706 MonoClass *klass = gparam->owner->owner.klass;
6707 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6708 is_type_done = FALSE;
6712 /* g_assert_not_reached (); */
6713 /* should this be considered an error condition? */
6714 if (is_type_done && !type->byref) {
6715 mono_domain_unlock (domain);
6716 mono_loader_unlock ();
6717 return mono_class_get_ref_info (klass);
6720 /* This is stored in vtables/JITted code so it has to be pinned */
6721 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6723 mono_g_hash_table_insert (domain->type_hash, type, res);
6725 if (type->type == MONO_TYPE_VOID)
6726 domain->typeof_void = (MonoObject*)res;
6728 mono_domain_unlock (domain);
6729 mono_loader_unlock ();
6734 * mono_method_get_object:
6735 * @domain: an app domain
6737 * @refclass: the reflected type (can be NULL)
6739 * Return an System.Reflection.MonoMethod object representing the method @method.
6741 MonoReflectionMethod*
6742 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6745 * We use the same C representation for methods and constructors, but the type
6746 * name in C# is different.
6748 static MonoClass *System_Reflection_MonoMethod = NULL;
6749 static MonoClass *System_Reflection_MonoCMethod = NULL;
6750 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6751 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6753 MonoReflectionMethod *ret;
6755 if (method->is_inflated) {
6756 MonoReflectionGenericMethod *gret;
6758 refclass = method->klass;
6759 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6760 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6761 if (!System_Reflection_MonoGenericCMethod)
6762 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6763 klass = System_Reflection_MonoGenericCMethod;
6765 if (!System_Reflection_MonoGenericMethod)
6766 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6767 klass = System_Reflection_MonoGenericMethod;
6769 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6770 gret->method.method = method;
6771 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6772 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6773 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6777 refclass = method->klass;
6779 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6780 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6781 if (!System_Reflection_MonoCMethod)
6782 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6783 klass = System_Reflection_MonoCMethod;
6786 if (!System_Reflection_MonoMethod)
6787 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6788 klass = System_Reflection_MonoMethod;
6790 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6791 ret->method = method;
6792 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6793 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6797 * mono_method_clear_object:
6799 * Clear the cached reflection objects for the dynamic method METHOD.
6802 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6805 g_assert (method_is_dynamic (method));
6807 klass = method->klass;
6809 clear_cached_object (domain, method, klass);
6810 klass = klass->parent;
6812 /* Added by mono_param_get_objects () */
6813 clear_cached_object (domain, &(method->signature), NULL);
6814 klass = method->klass;
6816 clear_cached_object (domain, &(method->signature), klass);
6817 klass = klass->parent;
6822 * mono_field_get_object:
6823 * @domain: an app domain
6827 * Return an System.Reflection.MonoField object representing the field @field
6830 MonoReflectionField*
6831 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6833 MonoReflectionField *res;
6834 static MonoClass *monofield_klass;
6836 CHECK_OBJECT (MonoReflectionField *, field, klass);
6837 if (!monofield_klass)
6838 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6839 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6842 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6844 if (is_field_on_inst (field)) {
6845 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6846 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6849 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6850 res->attrs = mono_field_get_flags (field);
6852 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6856 * mono_property_get_object:
6857 * @domain: an app domain
6859 * @property: a property
6861 * Return an System.Reflection.MonoProperty object representing the property @property
6864 MonoReflectionProperty*
6865 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6867 MonoReflectionProperty *res;
6868 static MonoClass *monoproperty_klass;
6870 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6871 if (!monoproperty_klass)
6872 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6873 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6875 res->property = property;
6876 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6880 * mono_event_get_object:
6881 * @domain: an app domain
6885 * Return an System.Reflection.MonoEvent object representing the event @event
6888 MonoReflectionEvent*
6889 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6891 MonoReflectionEvent *res;
6892 MonoReflectionMonoEvent *mono_event;
6893 static MonoClass *monoevent_klass;
6895 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6896 if (!monoevent_klass)
6897 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6898 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6899 mono_event->klass = klass;
6900 mono_event->event = event;
6901 res = (MonoReflectionEvent*)mono_event;
6902 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6906 * mono_get_reflection_missing_object:
6907 * @domain: Domain where the object lives
6909 * Returns the System.Reflection.Missing.Value singleton object
6910 * (of type System.Reflection.Missing).
6912 * Used as the value for ParameterInfo.DefaultValue when Optional
6916 mono_get_reflection_missing_object (MonoDomain *domain)
6919 static MonoClassField *missing_value_field = NULL;
6921 if (!missing_value_field) {
6922 MonoClass *missing_klass;
6923 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6924 mono_class_init (missing_klass);
6925 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6926 g_assert (missing_value_field);
6928 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6934 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6937 *dbnull = mono_get_dbnull_object (domain);
6942 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6944 if (!*reflection_missing)
6945 *reflection_missing = mono_get_reflection_missing_object (domain);
6946 return *reflection_missing;
6950 * mono_param_get_objects:
6951 * @domain: an app domain
6954 * Return an System.Reflection.ParameterInfo array object representing the parameters
6955 * in the method @method.
6958 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6960 static MonoClass *System_Reflection_ParameterInfo;
6961 static MonoClass *System_Reflection_ParameterInfo_array;
6963 MonoArray *res = NULL;
6964 MonoReflectionMethod *member = NULL;
6965 MonoReflectionParameter *param = NULL;
6966 char **names, **blobs = NULL;
6967 guint32 *types = NULL;
6968 MonoType *type = NULL;
6969 MonoObject *dbnull = NULL;
6970 MonoObject *missing = NULL;
6971 MonoMarshalSpec **mspecs;
6972 MonoMethodSignature *sig;
6973 MonoVTable *pinfo_vtable;
6976 if (!System_Reflection_ParameterInfo_array) {
6979 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6981 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6983 mono_memory_barrier ();
6984 System_Reflection_ParameterInfo = klass;
6987 klass = mono_array_class_get (klass, 1);
6988 mono_memory_barrier ();
6989 System_Reflection_ParameterInfo_array = klass;
6992 sig = mono_method_signature_checked (method, &error);
6993 if (!mono_error_ok (&error))
6994 mono_error_raise_exception (&error);
6996 if (!sig->param_count)
6997 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6999 /* Note: the cache is based on the address of the signature into the method
7000 * since we already cache MethodInfos with the method as keys.
7002 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7004 member = mono_method_get_object (domain, method, refclass);
7005 names = g_new (char *, sig->param_count);
7006 mono_method_get_param_names (method, (const char **) names);
7008 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7009 mono_method_get_marshal_info (method, mspecs);
7011 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7012 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7013 for (i = 0; i < sig->param_count; ++i) {
7014 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7015 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7016 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7017 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7018 param->PositionImpl = i;
7019 param->AttrsImpl = sig->params [i]->attrs;
7021 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7022 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7023 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7025 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7029 blobs = g_new0 (char *, sig->param_count);
7030 types = g_new0 (guint32, sig->param_count);
7031 get_default_param_value_blobs (method, blobs, types);
7034 /* Build MonoType for the type from the Constant Table */
7036 type = g_new0 (MonoType, 1);
7037 type->type = types [i];
7038 type->data.klass = NULL;
7039 if (types [i] == MONO_TYPE_CLASS)
7040 type->data.klass = mono_defaults.object_class;
7041 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7042 /* For enums, types [i] contains the base type */
7044 type->type = MONO_TYPE_VALUETYPE;
7045 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7047 type->data.klass = mono_class_from_mono_type (type);
7049 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7051 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7052 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7053 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7054 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7056 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7062 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7064 mono_array_setref (res, i, param);
7071 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7073 mono_metadata_free_marshal_spec (mspecs [i]);
7076 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7080 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7082 return mono_param_get_objects_internal (domain, method, NULL);
7086 * mono_method_body_get_object:
7087 * @domain: an app domain
7090 * Return an System.Reflection.MethodBody object representing the method @method.
7092 MonoReflectionMethodBody*
7093 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7095 static MonoClass *System_Reflection_MethodBody = NULL;
7096 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7097 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7098 MonoReflectionMethodBody *ret;
7099 MonoMethodHeader *header;
7101 guint32 method_rva, local_var_sig_token;
7103 unsigned char format, flags;
7106 /* for compatibility with .net */
7107 if (method_is_dynamic (method))
7108 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7110 if (!System_Reflection_MethodBody)
7111 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7112 if (!System_Reflection_LocalVariableInfo)
7113 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7114 if (!System_Reflection_ExceptionHandlingClause)
7115 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7117 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7119 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7120 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7121 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7122 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7125 image = method->klass->image;
7126 header = mono_method_get_header (method);
7128 if (!image_is_dynamic (image)) {
7129 /* Obtain local vars signature token */
7130 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7131 ptr = mono_image_rva_map (image, method_rva);
7132 flags = *(const unsigned char *) ptr;
7133 format = flags & METHOD_HEADER_FORMAT_MASK;
7135 case METHOD_HEADER_TINY_FORMAT:
7136 local_var_sig_token = 0;
7138 case METHOD_HEADER_FAT_FORMAT:
7142 local_var_sig_token = read32 (ptr);
7145 g_assert_not_reached ();
7148 local_var_sig_token = 0; //FIXME
7150 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7152 ret->init_locals = header->init_locals;
7153 ret->max_stack = header->max_stack;
7154 ret->local_var_sig_token = local_var_sig_token;
7155 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7156 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7159 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7160 for (i = 0; i < header->num_locals; ++i) {
7161 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7162 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7163 info->is_pinned = header->locals [i]->pinned;
7164 info->local_index = i;
7165 mono_array_setref (ret->locals, i, info);
7169 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7170 for (i = 0; i < header->num_clauses; ++i) {
7171 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7172 MonoExceptionClause *clause = &header->clauses [i];
7174 info->flags = clause->flags;
7175 info->try_offset = clause->try_offset;
7176 info->try_length = clause->try_len;
7177 info->handler_offset = clause->handler_offset;
7178 info->handler_length = clause->handler_len;
7179 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7180 info->filter_offset = clause->data.filter_offset;
7181 else if (clause->data.catch_class)
7182 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7184 mono_array_setref (ret->clauses, i, info);
7187 mono_metadata_free_mh (header);
7188 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7193 * mono_get_dbnull_object:
7194 * @domain: Domain where the object lives
7196 * Returns the System.DBNull.Value singleton object
7198 * Used as the value for ParameterInfo.DefaultValue
7201 mono_get_dbnull_object (MonoDomain *domain)
7204 static MonoClassField *dbnull_value_field = NULL;
7206 if (!dbnull_value_field) {
7207 MonoClass *dbnull_klass;
7208 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7209 mono_class_init (dbnull_klass);
7210 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7211 g_assert (dbnull_value_field);
7213 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7219 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7221 guint32 param_index, i, lastp, crow = 0;
7222 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7225 MonoClass *klass = method->klass;
7226 MonoImage *image = klass->image;
7227 MonoMethodSignature *methodsig = mono_method_signature (method);
7229 MonoTableInfo *constt;
7230 MonoTableInfo *methodt;
7231 MonoTableInfo *paramt;
7233 if (!methodsig->param_count)
7236 mono_class_init (klass);
7238 if (image_is_dynamic (klass->image)) {
7239 MonoReflectionMethodAux *aux;
7240 if (method->is_inflated)
7241 method = ((MonoMethodInflated*)method)->declaring;
7242 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7243 if (aux && aux->param_defaults) {
7244 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7245 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7250 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7251 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7252 constt = &image->tables [MONO_TABLE_CONSTANT];
7254 idx = mono_method_get_index (method) - 1;
7255 g_assert (idx != -1);
7257 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7258 if (idx + 1 < methodt->rows)
7259 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7261 lastp = paramt->rows + 1;
7263 for (i = param_index; i < lastp; ++i) {
7266 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7267 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7269 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7272 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7277 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7278 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7279 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7286 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7291 MonoType *basetype = type;
7296 klass = mono_class_from_mono_type (type);
7297 if (klass->valuetype) {
7298 object = mono_object_new (domain, klass);
7299 retval = ((gchar *) object + sizeof (MonoObject));
7300 if (klass->enumtype)
7301 basetype = mono_class_enum_basetype (klass);
7306 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7313 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7316 gboolean quoted = FALSE;
7318 memset (assembly, 0, sizeof (MonoAssemblyName));
7319 assembly->culture = "";
7320 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7327 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7338 /* Remove trailing whitespace */
7340 while (*s && g_ascii_isspace (*s))
7343 while (g_ascii_isspace (*p))
7346 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7348 assembly->major = strtoul (p, &s, 10);
7349 if (s == p || *s != '.')
7352 assembly->minor = strtoul (p, &s, 10);
7353 if (s == p || *s != '.')
7356 assembly->build = strtoul (p, &s, 10);
7357 if (s == p || *s != '.')
7360 assembly->revision = strtoul (p, &s, 10);
7364 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7366 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7367 assembly->culture = "";
7370 assembly->culture = p;
7371 while (*p && *p != ',') {
7375 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7377 if (strncmp (p, "null", 4) == 0) {
7382 while (*p && *p != ',') {
7385 len = (p - start + 1);
7386 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7387 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7388 g_strlcpy ((char*)assembly->public_key_token, start, len);
7391 while (*p && *p != ',')
7395 while (g_ascii_isspace (*p) || *p == ',') {
7409 * mono_reflection_parse_type:
7412 * Parse a type name as accepted by the GetType () method and output the info
7413 * extracted in the info structure.
7414 * the name param will be mangled, so, make a copy before passing it to this function.
7415 * The fields in info will be valid until the memory pointed to by name is valid.
7417 * See also mono_type_get_name () below.
7419 * Returns: 0 on parse error.
7422 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7423 MonoTypeNameParse *info)
7425 char *start, *p, *w, *last_point, *startn;
7426 int in_modifiers = 0;
7427 int isbyref = 0, rank = 0, isptr = 0;
7429 start = p = w = name;
7431 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7432 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7433 info->name = info->name_space = NULL;
7434 info->nested = NULL;
7435 info->modifiers = NULL;
7436 info->type_arguments = NULL;
7438 /* last_point separates the namespace from the name */
7441 while (*p == ' ') p++, start++, w++, name++;
7446 *p = 0; /* NULL terminate the name */
7448 info->nested = g_list_append (info->nested, startn);
7449 /* we have parsed the nesting namespace + name */
7453 info->name_space = start;
7455 info->name = last_point + 1;
7457 info->name_space = (char *)"";
7485 info->name_space = start;
7487 info->name = last_point + 1;
7489 info->name_space = (char *)"";
7496 if (isbyref) /* only one level allowed by the spec */
7500 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7504 if (isbyref) /* pointer to ref not okay */
7506 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7511 if (isbyref) /* array of ref and generic ref are not okay */
7513 //Decide if it's an array of a generic argument list
7518 if (*p == ',' || *p == '*' || *p == ']') { //array
7526 else if (*p == '*') /* '*' means unknown lower bound */
7527 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7534 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7536 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7539 info->type_arguments = g_ptr_array_new ();
7541 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7542 gboolean fqname = FALSE;
7544 g_ptr_array_add (info->type_arguments, subinfo);
7546 while (*p == ' ') p++;
7552 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7555 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7556 if (fqname && (*p != ']')) {
7564 while (*p && (*p != ']'))
7572 if (g_ascii_isspace (*aname)) {
7579 !assembly_name_to_aname (&subinfo->assembly, aname))
7581 } else if (fqname && (*p == ']')) {
7603 if (g_ascii_isspace (*p)) {
7610 return 0; /* missing assembly name */
7611 if (!assembly_name_to_aname (&info->assembly, p))
7617 if (info->assembly.name)
7620 // *w = 0; /* terminate class name */
7622 if (!info->name || !*info->name)
7626 /* add other consistency checks */
7631 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7633 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7637 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7639 gboolean type_resolve = FALSE;
7641 MonoImage *rootimage = image;
7643 if (info->assembly.name) {
7644 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7645 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7647 * This could happen in the AOT compiler case when the search hook is not
7650 assembly = image->assembly;
7652 /* then we must load the assembly ourselve - see #60439 */
7653 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7657 image = assembly->image;
7658 } else if (!image) {
7659 image = mono_defaults.corlib;
7662 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7663 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7664 image = mono_defaults.corlib;
7665 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7672 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7677 gboolean bounded = FALSE;
7680 image = mono_defaults.corlib;
7683 rootimage = mono_defaults.corlib;
7687 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7688 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7690 klass = mono_class_from_name (image, info->name_space, info->name);
7694 for (mod = info->nested; mod; mod = mod->next) {
7695 gpointer iter = NULL;
7699 mono_class_init (parent);
7701 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7703 char *nested_name, *nested_nspace;
7704 gboolean match = TRUE;
7706 lastp = strrchr (mod->data, '.');
7708 /* Nested classes can have namespaces */
7711 nested_name = g_strdup (lastp + 1);
7712 nspace_len = lastp - (char*)mod->data;
7713 nested_nspace = g_malloc (nspace_len + 1);
7714 memcpy (nested_nspace, mod->data, nspace_len);
7715 nested_nspace [nspace_len] = '\0';
7718 nested_name = mod->data;
7719 nested_nspace = NULL;
7722 if (nested_nspace) {
7724 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7727 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7733 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7736 if (strcmp (klass->name, nested_name) != 0)
7741 g_free (nested_name);
7742 g_free (nested_nspace);
7754 if (info->type_arguments) {
7755 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7756 MonoReflectionType *the_type;
7760 for (i = 0; i < info->type_arguments->len; i++) {
7761 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7763 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7764 if (!type_args [i]) {
7770 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7772 instance = mono_reflection_bind_generic_parameters (
7773 the_type, info->type_arguments->len, type_args);
7779 klass = mono_class_from_mono_type (instance);
7782 for (mod = info->modifiers; mod; mod = mod->next) {
7783 modval = GPOINTER_TO_UINT (mod->data);
7784 if (!modval) { /* byref: must be last modifier */
7785 return &klass->this_arg;
7786 } else if (modval == -1) {
7787 klass = mono_ptr_class_get (&klass->byval_arg);
7788 } else if (modval == -2) {
7790 } else { /* array rank */
7791 klass = mono_bounded_array_class_get (klass, modval, bounded);
7795 return &klass->byval_arg;
7799 * mono_reflection_get_type:
7800 * @image: a metadata context
7801 * @info: type description structure
7802 * @ignorecase: flag for case-insensitive string compares
7803 * @type_resolve: whenever type resolve was already tried
7805 * Build a MonoType from the type description in @info.
7810 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7811 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7815 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7817 MonoReflectionAssemblyBuilder *abuilder;
7821 g_assert (assembly_is_dynamic (assembly));
7822 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7824 /* Enumerate all modules */
7827 if (abuilder->modules) {
7828 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7829 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7830 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7836 if (!type && abuilder->loaded_modules) {
7837 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7838 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7839 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7849 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7852 MonoReflectionAssembly *assembly;
7856 if (image && image_is_dynamic (image))
7857 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7859 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7862 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7869 *type_resolve = TRUE;
7872 /* Reconstruct the type name */
7873 fullName = g_string_new ("");
7874 if (info->name_space && (info->name_space [0] != '\0'))
7875 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7877 g_string_printf (fullName, "%s", info->name);
7878 for (mod = info->nested; mod; mod = mod->next)
7879 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7881 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7883 if (assembly_is_dynamic (assembly->assembly))
7884 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7886 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7889 g_string_free (fullName, TRUE);
7894 mono_reflection_free_type_info (MonoTypeNameParse *info)
7896 g_list_free (info->modifiers);
7897 g_list_free (info->nested);
7899 if (info->type_arguments) {
7902 for (i = 0; i < info->type_arguments->len; i++) {
7903 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7905 mono_reflection_free_type_info (subinfo);
7906 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7910 g_ptr_array_free (info->type_arguments, TRUE);
7915 * mono_reflection_type_from_name:
7917 * @image: a metadata context (can be NULL).
7919 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7920 * it defaults to get the type from @image or, if @image is NULL or loading
7921 * from it fails, uses corlib.
7925 mono_reflection_type_from_name (char *name, MonoImage *image)
7927 MonoType *type = NULL;
7928 MonoTypeNameParse info;
7931 /* Make a copy since parse_type modifies its argument */
7932 tmp = g_strdup (name);
7934 /*g_print ("requested type %s\n", str);*/
7935 if (mono_reflection_parse_type (tmp, &info)) {
7936 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7940 mono_reflection_free_type_info (&info);
7945 * mono_reflection_get_token:
7947 * Return the metadata token of OBJ which should be an object
7948 * representing a metadata element.
7951 mono_reflection_get_token (MonoObject *obj)
7956 klass = obj->vtable->klass;
7958 if (strcmp (klass->name, "MethodBuilder") == 0) {
7959 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7961 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7962 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7963 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7965 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7966 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7967 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7969 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7970 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7971 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7972 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7973 } else if (strcmp (klass->name, "MonoType") == 0) {
7974 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7975 MonoClass *mc = mono_class_from_mono_type (type);
7976 if (!mono_class_init (mc))
7977 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7979 token = mc->type_token;
7980 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7981 strcmp (klass->name, "MonoMethod") == 0 ||
7982 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7983 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7984 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7985 if (m->method->is_inflated) {
7986 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7987 return inflated->declaring->token;
7989 token = m->method->token;
7991 } else if (strcmp (klass->name, "MonoField") == 0) {
7992 MonoReflectionField *f = (MonoReflectionField*)obj;
7994 if (is_field_on_inst (f->field)) {
7995 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7997 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7998 int field_index = f->field - dgclass->fields;
8001 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8002 obj = dgclass->field_objects [field_index];
8003 return mono_reflection_get_token (obj);
8006 token = mono_class_get_field_token (f->field);
8007 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8008 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8010 token = mono_class_get_property_token (p->property);
8011 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8012 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8014 token = mono_class_get_event_token (p->event);
8015 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8016 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8017 MonoClass *member_class = mono_object_class (p->MemberImpl);
8018 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8020 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8021 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8022 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8025 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8026 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8028 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8029 MonoException *ex = mono_get_exception_not_implemented (msg);
8031 mono_raise_exception (ex);
8038 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8042 int slen = mono_metadata_decode_value (p, &p);
8044 mono_error_init (error);
8046 n = g_memdup (p, slen + 1);
8048 t = mono_reflection_type_from_name (n, image);
8050 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8051 /* We don't free n, it's consumed by mono_error */
8052 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8058 return mono_class_from_mono_type (t);
8062 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8064 int slen, type = t->type;
8065 MonoClass *tklass = t->data.klass;
8067 mono_error_init (error);
8073 case MONO_TYPE_BOOLEAN: {
8074 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8079 case MONO_TYPE_CHAR:
8081 case MONO_TYPE_I2: {
8082 guint16 *val = g_malloc (sizeof (guint16));
8087 #if SIZEOF_VOID_P == 4
8093 case MONO_TYPE_I4: {
8094 guint32 *val = g_malloc (sizeof (guint32));
8099 #if SIZEOF_VOID_P == 8
8100 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8104 case MONO_TYPE_I8: {
8105 guint64 *val = g_malloc (sizeof (guint64));
8110 case MONO_TYPE_R8: {
8111 double *val = g_malloc (sizeof (double));
8116 case MONO_TYPE_VALUETYPE:
8117 if (t->data.klass->enumtype) {
8118 type = mono_class_enum_basetype (t->data.klass)->type;
8121 MonoClass *k = t->data.klass;
8123 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8124 guint64 *val = g_malloc (sizeof (guint64));
8130 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8133 case MONO_TYPE_STRING:
8134 if (*p == (char)0xFF) {
8138 slen = mono_metadata_decode_value (p, &p);
8140 return mono_string_new_len (mono_domain_get (), p, slen);
8141 case MONO_TYPE_CLASS: {
8144 if (*p == (char)0xFF) {
8149 slen = mono_metadata_decode_value (p, &p);
8150 n = g_memdup (p, slen + 1);
8152 t = mono_reflection_type_from_name (n, image);
8154 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8155 /* We don't free n, it's consumed by mono_error */
8156 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8161 return mono_type_get_object (mono_domain_get (), t);
8163 case MONO_TYPE_OBJECT: {
8166 MonoClass *subc = NULL;
8171 } else if (subt == 0x0E) {
8172 type = MONO_TYPE_STRING;
8174 } else if (subt == 0x1D) {
8175 MonoType simple_type = {{0}};
8179 type = MONO_TYPE_SZARRAY;
8180 if (etype == 0x50) {
8181 tklass = mono_defaults.systemtype_class;
8182 } else if (etype == 0x55) {
8183 tklass = load_cattr_enum_type (image, p, &p, error);
8184 if (!mono_error_ok (error))
8188 /* See Partition II, Appendix B3 */
8189 etype = MONO_TYPE_OBJECT;
8190 simple_type.type = etype;
8191 tklass = mono_class_from_mono_type (&simple_type);
8194 } else if (subt == 0x55) {
8197 slen = mono_metadata_decode_value (p, &p);
8198 n = g_memdup (p, slen + 1);
8200 t = mono_reflection_type_from_name (n, image);
8202 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8203 /* We don't free n, it's consumed by mono_error */
8204 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8209 subc = mono_class_from_mono_type (t);
8210 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8211 MonoType simple_type = {{0}};
8212 simple_type.type = subt;
8213 subc = mono_class_from_mono_type (&simple_type);
8215 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8217 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8219 if (mono_error_ok (error)) {
8220 obj = mono_object_new (mono_domain_get (), subc);
8221 g_assert (!subc->has_references);
8222 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8228 case MONO_TYPE_SZARRAY: {
8230 guint32 i, alen, basetype;
8233 if (alen == 0xffffffff) {
8237 arr = mono_array_new (mono_domain_get(), tklass, alen);
8238 basetype = tklass->byval_arg.type;
8239 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8240 basetype = mono_class_enum_basetype (tklass)->type;
8245 case MONO_TYPE_BOOLEAN:
8246 for (i = 0; i < alen; i++) {
8247 MonoBoolean val = *p++;
8248 mono_array_set (arr, MonoBoolean, i, val);
8251 case MONO_TYPE_CHAR:
8254 for (i = 0; i < alen; i++) {
8255 guint16 val = read16 (p);
8256 mono_array_set (arr, guint16, i, val);
8263 for (i = 0; i < alen; i++) {
8264 guint32 val = read32 (p);
8265 mono_array_set (arr, guint32, i, val);
8270 for (i = 0; i < alen; i++) {
8273 mono_array_set (arr, double, i, val);
8279 for (i = 0; i < alen; i++) {
8280 guint64 val = read64 (p);
8281 mono_array_set (arr, guint64, i, val);
8285 case MONO_TYPE_CLASS:
8286 case MONO_TYPE_OBJECT:
8287 case MONO_TYPE_STRING:
8288 case MONO_TYPE_SZARRAY:
8289 for (i = 0; i < alen; i++) {
8290 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8291 if (!mono_error_ok (error))
8293 mono_array_setref (arr, i, item);
8297 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8303 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8309 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8311 static MonoClass *klass;
8312 static MonoMethod *ctor;
8314 void *params [2], *unboxed;
8317 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8319 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8321 params [0] = mono_type_get_object (mono_domain_get (), t);
8323 retval = mono_object_new (mono_domain_get (), klass);
8324 unboxed = mono_object_unbox (retval);
8325 mono_runtime_invoke (ctor, unboxed, params, NULL);
8331 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8333 static MonoClass *klass;
8334 static MonoMethod *ctor;
8336 void *unboxed, *params [2];
8339 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8341 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8344 params [1] = typedarg;
8345 retval = mono_object_new (mono_domain_get (), klass);
8346 unboxed = mono_object_unbox (retval);
8347 mono_runtime_invoke (ctor, unboxed, params, NULL);
8353 type_is_reference (MonoType *type)
8355 switch (type->type) {
8356 case MONO_TYPE_BOOLEAN:
8357 case MONO_TYPE_CHAR:
8370 case MONO_TYPE_VALUETYPE:
8378 free_param_data (MonoMethodSignature *sig, void **params) {
8380 for (i = 0; i < sig->param_count; ++i) {
8381 if (!type_is_reference (sig->params [i]))
8382 g_free (params [i]);
8387 * Find the field index in the metadata FieldDef table.
8390 find_field_index (MonoClass *klass, MonoClassField *field) {
8393 for (i = 0; i < klass->field.count; ++i) {
8394 if (field == &klass->fields [i])
8395 return klass->field.first + 1 + i;
8401 * Find the property index in the metadata Property table.
8404 find_property_index (MonoClass *klass, MonoProperty *property) {
8407 for (i = 0; i < klass->ext->property.count; ++i) {
8408 if (property == &klass->ext->properties [i])
8409 return klass->ext->property.first + 1 + i;
8415 * Find the event index in the metadata Event table.
8418 find_event_index (MonoClass *klass, MonoEvent *event) {
8421 for (i = 0; i < klass->ext->event.count; ++i) {
8422 if (event == &klass->ext->events [i])
8423 return klass->ext->event.first + 1 + i;
8429 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8431 const char *p = (const char*)data;
8433 guint32 i, j, num_named;
8435 void *params_buf [32];
8436 void **params = NULL;
8437 MonoMethodSignature *sig;
8438 MonoObject *exc = NULL;
8440 mono_error_init (error);
8442 mono_class_init (method->klass);
8444 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8445 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8450 attr = mono_object_new (mono_domain_get (), method->klass);
8451 mono_runtime_invoke (method, attr, NULL, NULL);
8455 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8458 /*g_print ("got attr %s\n", method->klass->name);*/
8460 sig = mono_method_signature (method);
8461 if (sig->param_count < 32) {
8462 params = params_buf;
8463 memset (params, 0, sizeof (void*) * sig->param_count);
8465 /* Allocate using GC so it gets GC tracking */
8466 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8471 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8472 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8473 if (!mono_error_ok (error))
8478 attr = mono_object_new (mono_domain_get (), method->klass);
8480 mono_runtime_invoke (method, attr, params, &exc);
8483 num_named = read16 (named);
8485 for (j = 0; j < num_named; j++) {
8487 char *name, named_type, data_type;
8488 named_type = *named++;
8489 data_type = *named++; /* type of data */
8490 if (data_type == MONO_TYPE_SZARRAY)
8491 data_type = *named++;
8492 if (data_type == MONO_TYPE_ENUM) {
8495 type_len = mono_metadata_decode_blob_size (named, &named);
8496 type_name = g_malloc (type_len + 1);
8497 memcpy (type_name, named, type_len);
8498 type_name [type_len] = 0;
8500 /* FIXME: lookup the type and check type consistency */
8503 name_len = mono_metadata_decode_blob_size (named, &named);
8504 name = g_malloc (name_len + 1);
8505 memcpy (name, named, name_len);
8506 name [name_len] = 0;
8508 if (named_type == 0x53) {
8509 MonoClassField *field;
8512 /* how this fail is a blackbox */
8513 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8515 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8520 val = load_cattr_value (image, field->type, named, &named, error);
8521 if (!mono_error_ok (error)) {
8523 if (!type_is_reference (field->type))
8528 mono_field_set_value (attr, field, val);
8529 if (!type_is_reference (field->type))
8531 } else if (named_type == 0x54) {
8534 MonoType *prop_type;
8536 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8539 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8545 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8550 /* can we have more that 1 arg in a custom attr named property? */
8551 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8552 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8554 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8555 if (!mono_error_ok (error)) {
8557 if (!type_is_reference (prop_type))
8558 g_free (pparams [0]);
8563 mono_property_set_value (prop, attr, pparams, NULL);
8564 if (!type_is_reference (prop_type))
8565 g_free (pparams [0]);
8570 free_param_data (method->signature, params);
8571 if (params != params_buf)
8572 mono_gc_free_fixed (params);
8577 free_param_data (method->signature, params);
8578 if (params != params_buf)
8579 mono_gc_free_fixed (params);
8581 mono_raise_exception ((MonoException*)exc);
8586 * mono_reflection_create_custom_attr_data_args:
8588 * Create an array of typed and named arguments from the cattr blob given by DATA.
8589 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8590 * NAMED_ARG_INFO will contain information about the named arguments.
8593 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
8595 MonoArray *typedargs, *namedargs;
8596 MonoClass *attrklass;
8598 const char *p = (const char*)data;
8600 guint32 i, j, num_named;
8601 CattrNamedArg *arginfo = NULL;
8605 *named_arg_info = NULL;
8607 mono_error_init (error);
8609 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8610 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8614 mono_class_init (method->klass);
8616 domain = mono_domain_get ();
8618 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8621 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8625 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8629 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8630 if (!mono_error_ok (error)) {
8631 if (!type_is_reference (mono_method_signature (method)->params [i]))
8636 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8637 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8638 mono_array_setref (typedargs, i, obj);
8640 if (!type_is_reference (mono_method_signature (method)->params [i]))
8645 num_named = read16 (named);
8646 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8648 attrklass = method->klass;
8650 arginfo = g_new0 (CattrNamedArg, num_named);
8651 *named_arg_info = arginfo;
8653 for (j = 0; j < num_named; j++) {
8655 char *name, named_type, data_type;
8656 named_type = *named++;
8657 data_type = *named++; /* type of data */
8658 if (data_type == MONO_TYPE_SZARRAY)
8659 data_type = *named++;
8660 if (data_type == MONO_TYPE_ENUM) {
8663 type_len = mono_metadata_decode_blob_size (named, &named);
8664 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8667 type_name = g_malloc (type_len + 1);
8668 memcpy (type_name, named, type_len);
8669 type_name [type_len] = 0;
8671 /* FIXME: lookup the type and check type consistency */
8674 name_len = mono_metadata_decode_blob_size (named, &named);
8675 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8677 name = g_malloc (name_len + 1);
8678 memcpy (name, named, name_len);
8679 name [name_len] = 0;
8681 if (named_type == 0x53) {
8683 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8691 arginfo [j].type = field->type;
8692 arginfo [j].field = field;
8694 val = load_cattr_value (image, field->type, named, &named, error);
8695 if (!mono_error_ok (error)) {
8696 if (!type_is_reference (field->type))
8702 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8703 mono_array_setref (namedargs, j, obj);
8704 if (!type_is_reference (field->type))
8706 } else if (named_type == 0x54) {
8708 MonoType *prop_type;
8709 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8712 if (!prop || !prop->set) {
8717 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8718 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8720 arginfo [j].type = prop_type;
8721 arginfo [j].prop = prop;
8723 val = load_cattr_value (image, prop_type, named, &named, error);
8724 if (!mono_error_ok (error)) {
8725 if (!type_is_reference (prop_type))
8731 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8732 mono_array_setref (namedargs, j, obj);
8733 if (!type_is_reference (prop_type))
8739 *typed_args = typedargs;
8740 *named_args = namedargs;
8743 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8745 *named_arg_info = NULL;
8749 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8752 MonoArray *typedargs, *namedargs;
8755 CattrNamedArg *arginfo = NULL;
8765 image = assembly->assembly->image;
8766 method = ref_method->method;
8767 domain = mono_object_domain (ref_method);
8769 if (!mono_class_init (method->klass))
8770 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8772 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8773 if (!mono_error_ok (&error))
8774 mono_error_raise_exception (&error);
8775 if (mono_loader_get_last_error ())
8776 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8778 if (!typedargs || !namedargs) {
8783 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8784 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8785 MonoObject *typedarg;
8787 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8788 mono_array_setref (typedargs, i, typedarg);
8791 for (i = 0; i < mono_array_length (namedargs); ++i) {
8792 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8793 MonoObject *typedarg, *namedarg, *minfo;
8795 if (arginfo [i].prop)
8796 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8798 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8800 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8801 namedarg = create_cattr_named_arg (minfo, typedarg);
8803 mono_array_setref (namedargs, i, namedarg);
8806 *ctor_args = typedargs;
8807 *named_args = namedargs;
8812 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8814 static MonoMethod *ctor;
8819 g_assert (image->assembly);
8822 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8824 domain = mono_domain_get ();
8825 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8826 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8827 params [1] = mono_assembly_get_object (domain, image->assembly);
8828 params [2] = (gpointer)&cattr->data;
8829 params [3] = &cattr->data_size;
8830 mono_runtime_invoke (ctor, attr, params, NULL);
8835 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8841 mono_error_init (error);
8844 for (i = 0; i < cinfo->num_attrs; ++i) {
8845 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8849 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8851 for (i = 0; i < cinfo->num_attrs; ++i) {
8852 if (!cinfo->attrs [i].ctor)
8853 /* The cattr type is not finished yet */
8854 /* We should include the type name but cinfo doesn't contain it */
8855 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8856 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8857 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8858 if (!mono_error_ok (error))
8860 mono_array_setref (result, n, attr);
8868 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8871 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8872 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8878 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8884 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8885 for (i = 0; i < cinfo->num_attrs; ++i) {
8886 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8887 mono_array_setref (result, i, attr);
8893 * mono_custom_attrs_from_index:
8895 * Returns: NULL if no attributes are found or if a loading error occurs.
8898 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8900 guint32 mtoken, i, len;
8901 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8903 MonoCustomAttrInfo *ainfo;
8904 GList *tmp, *list = NULL;
8906 MonoCustomAttrEntry* attr;
8908 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8910 i = mono_metadata_custom_attrs_from_index (image, idx);
8914 while (i < ca->rows) {
8915 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8917 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8920 len = g_list_length (list);
8923 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8924 ainfo->num_attrs = len;
8925 ainfo->image = image;
8926 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8927 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8928 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8929 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8930 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8931 mtoken |= MONO_TOKEN_METHOD_DEF;
8933 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8934 mtoken |= MONO_TOKEN_MEMBER_REF;
8937 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8940 attr = &ainfo->attrs [i - 1];
8941 attr->ctor = mono_get_method (image, mtoken, NULL);
8943 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8949 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8950 /*FIXME raising an exception here doesn't make any sense*/
8951 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8956 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8957 attr->data_size = mono_metadata_decode_value (data, &data);
8958 attr->data = (guchar*)data;
8966 mono_custom_attrs_from_method (MonoMethod *method)
8971 * An instantiated method has the same cattrs as the generic method definition.
8973 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8974 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8976 if (method->is_inflated)
8977 method = ((MonoMethodInflated *) method)->declaring;
8979 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8980 return lookup_custom_attr (method->klass->image, method);
8983 /* Synthetic methods */
8986 idx = mono_method_get_index (method);
8987 idx <<= MONO_CUSTOM_ATTR_BITS;
8988 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8989 return mono_custom_attrs_from_index (method->klass->image, idx);
8993 mono_custom_attrs_from_class (MonoClass *klass)
8997 if (klass->generic_class)
8998 klass = klass->generic_class->container_class;
9000 if (image_is_dynamic (klass->image))
9001 return lookup_custom_attr (klass->image, klass);
9003 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9004 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9005 idx <<= MONO_CUSTOM_ATTR_BITS;
9006 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9008 idx = mono_metadata_token_index (klass->type_token);
9009 idx <<= MONO_CUSTOM_ATTR_BITS;
9010 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9012 return mono_custom_attrs_from_index (klass->image, idx);
9016 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9020 if (image_is_dynamic (assembly->image))
9021 return lookup_custom_attr (assembly->image, assembly);
9022 idx = 1; /* there is only one assembly */
9023 idx <<= MONO_CUSTOM_ATTR_BITS;
9024 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9025 return mono_custom_attrs_from_index (assembly->image, idx);
9028 static MonoCustomAttrInfo*
9029 mono_custom_attrs_from_module (MonoImage *image)
9033 if (image_is_dynamic (image))
9034 return lookup_custom_attr (image, image);
9035 idx = 1; /* there is only one module */
9036 idx <<= MONO_CUSTOM_ATTR_BITS;
9037 idx |= MONO_CUSTOM_ATTR_MODULE;
9038 return mono_custom_attrs_from_index (image, idx);
9042 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9046 if (image_is_dynamic (klass->image)) {
9047 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9048 return lookup_custom_attr (klass->image, property);
9050 idx = find_property_index (klass, property);
9051 idx <<= MONO_CUSTOM_ATTR_BITS;
9052 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9053 return mono_custom_attrs_from_index (klass->image, idx);
9057 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9061 if (image_is_dynamic (klass->image)) {
9062 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9063 return lookup_custom_attr (klass->image, event);
9065 idx = find_event_index (klass, event);
9066 idx <<= MONO_CUSTOM_ATTR_BITS;
9067 idx |= MONO_CUSTOM_ATTR_EVENT;
9068 return mono_custom_attrs_from_index (klass->image, idx);
9072 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9075 if (image_is_dynamic (klass->image)) {
9076 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9077 return lookup_custom_attr (klass->image, field);
9079 idx = find_field_index (klass, field);
9080 idx <<= MONO_CUSTOM_ATTR_BITS;
9081 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9082 return mono_custom_attrs_from_index (klass->image, idx);
9086 * mono_custom_attrs_from_param:
9087 * @method: handle to the method that we want to retrieve custom parameter information from
9088 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9090 * The result must be released with mono_custom_attrs_free().
9092 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9095 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9098 guint32 i, idx, method_index;
9099 guint32 param_list, param_last, param_pos, found;
9101 MonoReflectionMethodAux *aux;
9104 * An instantiated method has the same cattrs as the generic method definition.
9106 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9107 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9109 if (method->is_inflated)
9110 method = ((MonoMethodInflated *) method)->declaring;
9112 if (image_is_dynamic (method->klass->image)) {
9113 MonoCustomAttrInfo *res, *ainfo;
9116 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9117 if (!aux || !aux->param_cattr)
9120 /* Need to copy since it will be freed later */
9121 ainfo = aux->param_cattr [param];
9124 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9125 res = g_malloc0 (size);
9126 memcpy (res, ainfo, size);
9130 image = method->klass->image;
9131 method_index = mono_method_get_index (method);
9134 ca = &image->tables [MONO_TABLE_METHOD];
9136 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9137 if (method_index == ca->rows) {
9138 ca = &image->tables [MONO_TABLE_PARAM];
9139 param_last = ca->rows + 1;
9141 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9142 ca = &image->tables [MONO_TABLE_PARAM];
9145 for (i = param_list; i < param_last; ++i) {
9146 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9147 if (param_pos == param) {
9155 idx <<= MONO_CUSTOM_ATTR_BITS;
9156 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9157 return mono_custom_attrs_from_index (image, idx);
9161 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9165 for (i = 0; i < ainfo->num_attrs; ++i) {
9166 klass = ainfo->attrs [i].ctor->klass;
9167 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9174 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9177 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9178 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9183 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9189 mono_error_init (error);
9192 for (i = 0; i < ainfo->num_attrs; ++i) {
9193 klass = ainfo->attrs [i].ctor->klass;
9194 if (mono_class_has_parent (klass, attr_klass)) {
9199 if (attr_index == -1)
9202 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9203 if (!mono_error_ok (error))
9205 return mono_array_get (attrs, MonoObject*, attr_index);
9209 * mono_reflection_get_custom_attrs_info:
9210 * @obj: a reflection object handle
9212 * Return the custom attribute info for attributes defined for the
9213 * reflection handle @obj. The objects.
9215 * FIXME this function leaks like a sieve for SRE objects.
9218 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9221 MonoCustomAttrInfo *cinfo = NULL;
9223 klass = obj->vtable->klass;
9224 if (klass == mono_defaults.monotype_class) {
9225 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9226 klass = mono_class_from_mono_type (type);
9227 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9228 cinfo = mono_custom_attrs_from_class (klass);
9229 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9230 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9231 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9232 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9233 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9234 cinfo = mono_custom_attrs_from_module (module->image);
9235 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9236 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9237 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9238 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9239 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9240 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9241 } else if (strcmp ("MonoField", klass->name) == 0) {
9242 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9243 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9244 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9245 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9246 cinfo = mono_custom_attrs_from_method (rmethod->method);
9247 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9248 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9249 cinfo = mono_custom_attrs_from_method (rmethod->method);
9250 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9251 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9252 MonoClass *member_class = mono_object_class (param->MemberImpl);
9253 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9254 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9255 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9256 } else if (is_sr_mono_property (member_class)) {
9257 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9259 if (!(method = prop->property->get))
9260 method = prop->property->set;
9263 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9265 #ifndef DISABLE_REFLECTION_EMIT
9266 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9267 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9268 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9269 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9270 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9271 MonoMethod *method = NULL;
9272 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9273 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9274 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9275 method = ((MonoReflectionMethod *)c->cb)->method;
9277 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));
9279 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9283 char *type_name = mono_type_get_full_name (member_class);
9284 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9285 MonoException *ex = mono_get_exception_not_supported (msg);
9288 mono_raise_exception (ex);
9290 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9291 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9292 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9293 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9294 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9295 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9296 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9297 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9298 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9299 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9300 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9301 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9302 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9303 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9304 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9305 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9306 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9307 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9308 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9309 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9310 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9311 } else { /* handle other types here... */
9312 g_error ("get custom attrs not yet supported for %s", klass->name);
9319 * mono_reflection_get_custom_attrs_by_type:
9320 * @obj: a reflection object handle
9322 * Return an array with all the custom attributes defined of the
9323 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9324 * of that type are returned. The objects are fully build. Return NULL if a loading error
9328 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9331 MonoCustomAttrInfo *cinfo;
9333 mono_error_init (error);
9335 cinfo = mono_reflection_get_custom_attrs_info (obj);
9337 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9339 mono_custom_attrs_free (cinfo);
9341 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9342 if (mono_loader_get_last_error ())
9344 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9351 * mono_reflection_get_custom_attrs:
9352 * @obj: a reflection object handle
9354 * Return an array with all the custom attributes defined of the
9355 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9359 mono_reflection_get_custom_attrs (MonoObject *obj)
9363 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9367 * mono_reflection_get_custom_attrs_data:
9368 * @obj: a reflection obj handle
9370 * Returns an array of System.Reflection.CustomAttributeData,
9371 * which include information about attributes reflected on
9372 * types loaded using the Reflection Only methods
9375 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9378 MonoCustomAttrInfo *cinfo;
9380 cinfo = mono_reflection_get_custom_attrs_info (obj);
9382 result = mono_custom_attrs_data_construct (cinfo);
9384 mono_custom_attrs_free (cinfo);
9386 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9391 static MonoReflectionType*
9392 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9394 static MonoMethod *method_get_underlying_system_type = NULL;
9395 MonoMethod *usertype_method;
9397 if (!method_get_underlying_system_type)
9398 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9399 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9400 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9405 is_corlib_type (MonoClass *class)
9407 return class->image == mono_defaults.corlib;
9410 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9411 static MonoClass *cached_class; \
9413 return cached_class == _class; \
9414 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9415 cached_class = _class; \
9422 #ifndef DISABLE_REFLECTION_EMIT
9424 is_sre_array (MonoClass *class)
9426 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9430 is_sre_byref (MonoClass *class)
9432 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9436 is_sre_pointer (MonoClass *class)
9438 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9442 is_sre_generic_instance (MonoClass *class)
9444 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9448 is_sre_type_builder (MonoClass *class)
9450 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9454 is_sre_method_builder (MonoClass *class)
9456 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9460 is_sre_ctor_builder (MonoClass *class)
9462 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9466 is_sre_field_builder (MonoClass *class)
9468 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9472 is_sre_method_on_tb_inst (MonoClass *class)
9474 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9478 is_sre_ctor_on_tb_inst (MonoClass *class)
9480 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9484 mono_reflection_type_get_handle (MonoReflectionType* ref)
9492 if (is_usertype (ref)) {
9493 ref = mono_reflection_type_get_underlying_system_type (ref);
9494 if (ref == NULL || is_usertype (ref))
9500 class = mono_object_class (ref);
9502 if (is_sre_array (class)) {
9504 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9505 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9507 if (sre_array->rank == 0) //single dimentional array
9508 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9510 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9511 sre_array->type.type = res;
9513 } else if (is_sre_byref (class)) {
9515 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9516 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9518 res = &mono_class_from_mono_type (base)->this_arg;
9519 sre_byref->type.type = res;
9521 } else if (is_sre_pointer (class)) {
9523 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9524 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9526 res = &mono_ptr_class_get (base)->byval_arg;
9527 sre_pointer->type.type = res;
9529 } else if (is_sre_generic_instance (class)) {
9530 MonoType *res, **types;
9531 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9534 count = mono_array_length (gclass->type_arguments);
9535 types = g_new0 (MonoType*, count);
9536 for (i = 0; i < count; ++i) {
9537 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9538 types [i] = mono_reflection_type_get_handle (t);
9545 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9548 gclass->type.type = res;
9552 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9559 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9561 mono_reflection_type_get_handle (type);
9565 mono_reflection_register_with_runtime (MonoReflectionType *type)
9567 MonoType *res = mono_reflection_type_get_handle (type);
9568 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9572 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9574 class = mono_class_from_mono_type (res);
9576 mono_loader_lock (); /*same locking as mono_type_get_object*/
9577 mono_domain_lock (domain);
9579 if (!image_is_dynamic (class->image)) {
9580 mono_class_setup_supertypes (class);
9582 if (!domain->type_hash)
9583 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9584 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9585 mono_g_hash_table_insert (domain->type_hash, res, type);
9587 mono_domain_unlock (domain);
9588 mono_loader_unlock ();
9592 * LOCKING: Assumes the loader lock is held.
9594 static MonoMethodSignature*
9595 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9596 MonoMethodSignature *sig;
9599 count = parameters? mono_array_length (parameters): 0;
9601 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9602 sig->param_count = count;
9603 sig->sentinelpos = -1; /* FIXME */
9604 for (i = 0; i < count; ++i)
9605 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9610 * LOCKING: Assumes the loader lock is held.
9612 static MonoMethodSignature*
9613 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9614 MonoMethodSignature *sig;
9616 sig = parameters_to_signature (image, ctor->parameters);
9617 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9618 sig->ret = &mono_defaults.void_class->byval_arg;
9623 * LOCKING: Assumes the loader lock is held.
9625 static MonoMethodSignature*
9626 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9627 MonoMethodSignature *sig;
9629 sig = parameters_to_signature (image, method->parameters);
9630 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9631 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9632 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9636 static MonoMethodSignature*
9637 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9638 MonoMethodSignature *sig;
9640 sig = parameters_to_signature (NULL, method->parameters);
9641 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9642 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9643 sig->generic_param_count = 0;
9648 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9650 MonoClass *klass = mono_object_class (prop);
9651 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9652 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9653 *name = mono_string_to_utf8 (pb->name);
9654 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9656 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9657 *name = g_strdup (p->property->name);
9658 if (p->property->get)
9659 *type = mono_method_signature (p->property->get)->ret;
9661 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9666 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9668 MonoClass *klass = mono_object_class (field);
9669 if (strcmp (klass->name, "FieldBuilder") == 0) {
9670 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9671 *name = mono_string_to_utf8 (fb->name);
9672 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9674 MonoReflectionField *f = (MonoReflectionField *)field;
9675 *name = g_strdup (mono_field_get_name (f->field));
9676 *type = f->field->type;
9680 #else /* DISABLE_REFLECTION_EMIT */
9683 mono_reflection_register_with_runtime (MonoReflectionType *type)
9689 is_sre_type_builder (MonoClass *class)
9695 is_sre_generic_instance (MonoClass *class)
9701 init_type_builder_generics (MonoObject *type)
9705 #endif /* !DISABLE_REFLECTION_EMIT */
9709 is_sr_mono_field (MonoClass *class)
9711 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9715 is_sr_mono_property (MonoClass *class)
9717 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9721 is_sr_mono_method (MonoClass *class)
9723 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9727 is_sr_mono_cmethod (MonoClass *class)
9729 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9733 is_sr_mono_generic_method (MonoClass *class)
9735 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9739 is_sr_mono_generic_cmethod (MonoClass *class)
9741 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9745 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9747 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9751 is_usertype (MonoReflectionType *ref)
9753 MonoClass *class = mono_object_class (ref);
9754 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9757 static MonoReflectionType*
9758 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9760 if (!type || type->type)
9763 if (is_usertype (type)) {
9764 type = mono_reflection_type_get_underlying_system_type (type);
9765 if (is_usertype (type))
9766 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9772 * Encode a value in a custom attribute stream of bytes.
9773 * The value to encode is either supplied as an object in argument val
9774 * (valuetypes are boxed), or as a pointer to the data in the
9776 * @type represents the type of the value
9777 * @buffer is the start of the buffer
9778 * @p the current position in the buffer
9779 * @buflen contains the size of the buffer and is used to return the new buffer size
9780 * if this needs to be realloced.
9781 * @retbuffer and @retp return the start and the position of the buffer
9784 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9786 MonoTypeEnum simple_type;
9788 if ((p-buffer) + 10 >= *buflen) {
9791 newbuf = g_realloc (buffer, *buflen);
9792 p = newbuf + (p-buffer);
9796 argval = ((char*)arg + sizeof (MonoObject));
9797 simple_type = type->type;
9799 switch (simple_type) {
9800 case MONO_TYPE_BOOLEAN:
9805 case MONO_TYPE_CHAR:
9808 swap_with_size (p, argval, 2, 1);
9814 swap_with_size (p, argval, 4, 1);
9818 swap_with_size (p, argval, 8, 1);
9823 swap_with_size (p, argval, 8, 1);
9826 case MONO_TYPE_VALUETYPE:
9827 if (type->data.klass->enumtype) {
9828 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9831 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9834 case MONO_TYPE_STRING: {
9841 str = mono_string_to_utf8 ((MonoString*)arg);
9842 slen = strlen (str);
9843 if ((p-buffer) + 10 + slen >= *buflen) {
9847 newbuf = g_realloc (buffer, *buflen);
9848 p = newbuf + (p-buffer);
9851 mono_metadata_encode_value (slen, p, &p);
9852 memcpy (p, str, slen);
9857 case MONO_TYPE_CLASS: {
9865 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9866 slen = strlen (str);
9867 if ((p-buffer) + 10 + slen >= *buflen) {
9871 newbuf = g_realloc (buffer, *buflen);
9872 p = newbuf + (p-buffer);
9875 mono_metadata_encode_value (slen, p, &p);
9876 memcpy (p, str, slen);
9881 case MONO_TYPE_SZARRAY: {
9883 MonoClass *eclass, *arg_eclass;
9886 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9889 len = mono_array_length ((MonoArray*)arg);
9891 *p++ = (len >> 8) & 0xff;
9892 *p++ = (len >> 16) & 0xff;
9893 *p++ = (len >> 24) & 0xff;
9895 *retbuffer = buffer;
9896 eclass = type->data.klass;
9897 arg_eclass = mono_object_class (arg)->element_class;
9900 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9901 eclass = mono_defaults.object_class;
9903 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9904 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9905 int elsize = mono_class_array_element_size (arg_eclass);
9906 for (i = 0; i < len; ++i) {
9907 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9910 } else if (eclass->valuetype && arg_eclass->valuetype) {
9911 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9912 int elsize = mono_class_array_element_size (eclass);
9913 for (i = 0; i < len; ++i) {
9914 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9918 for (i = 0; i < len; ++i) {
9919 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9924 case MONO_TYPE_OBJECT: {
9930 * The parameter type is 'object' but the type of the actual
9931 * argument is not. So we have to add type information to the blob
9932 * too. This is completely undocumented in the spec.
9936 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9941 klass = mono_object_class (arg);
9943 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9946 } else if (klass->enumtype) {
9948 } else if (klass == mono_defaults.string_class) {
9949 simple_type = MONO_TYPE_STRING;
9952 } else if (klass->rank == 1) {
9954 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9955 /* See Partition II, Appendix B3 */
9958 *p++ = klass->element_class->byval_arg.type;
9959 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9961 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9962 *p++ = simple_type = klass->byval_arg.type;
9965 g_error ("unhandled type in custom attr");
9967 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9968 slen = strlen (str);
9969 if ((p-buffer) + 10 + slen >= *buflen) {
9973 newbuf = g_realloc (buffer, *buflen);
9974 p = newbuf + (p-buffer);
9977 mono_metadata_encode_value (slen, p, &p);
9978 memcpy (p, str, slen);
9981 simple_type = mono_class_enum_basetype (klass)->type;
9985 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9988 *retbuffer = buffer;
9992 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9994 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9995 char *str = type_get_qualified_name (type, NULL);
9996 int slen = strlen (str);
10000 * This seems to be optional...
10003 mono_metadata_encode_value (slen, p, &p);
10004 memcpy (p, str, slen);
10007 } else if (type->type == MONO_TYPE_OBJECT) {
10009 } else if (type->type == MONO_TYPE_CLASS) {
10010 /* it should be a type: encode_cattr_value () has the check */
10013 mono_metadata_encode_value (type->type, p, &p);
10014 if (type->type == MONO_TYPE_SZARRAY)
10015 /* See the examples in Partition VI, Annex B */
10016 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10022 #ifndef DISABLE_REFLECTION_EMIT
10024 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10027 /* Preallocate a large enough buffer */
10028 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10029 char *str = type_get_qualified_name (type, NULL);
10030 len = strlen (str);
10032 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10033 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10034 len = strlen (str);
10039 len += strlen (name);
10041 if ((p-buffer) + 20 + len >= *buflen) {
10045 newbuf = g_realloc (buffer, *buflen);
10046 p = newbuf + (p-buffer);
10050 encode_field_or_prop_type (type, p, &p);
10052 len = strlen (name);
10053 mono_metadata_encode_value (len, p, &p);
10054 memcpy (p, name, len);
10056 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10058 *retbuffer = buffer;
10062 * mono_reflection_get_custom_attrs_blob:
10063 * @ctor: custom attribute constructor
10064 * @ctorArgs: arguments o the constructor
10070 * Creates the blob of data that needs to be saved in the metadata and that represents
10071 * the custom attributed described by @ctor, @ctorArgs etc.
10072 * Returns: a Byte array representing the blob of data.
10075 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10078 MonoMethodSignature *sig;
10083 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10084 /* sig is freed later so allocate it in the heap */
10085 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10087 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10090 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10092 p = buffer = g_malloc (buflen);
10093 /* write the prolog */
10096 for (i = 0; i < sig->param_count; ++i) {
10097 arg = mono_array_get (ctorArgs, MonoObject*, i);
10098 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10102 i += mono_array_length (properties);
10104 i += mono_array_length (fields);
10106 *p++ = (i >> 8) & 0xff;
10109 for (i = 0; i < mono_array_length (properties); ++i) {
10113 prop = mono_array_get (properties, gpointer, i);
10114 get_prop_name_and_type (prop, &pname, &ptype);
10115 *p++ = 0x54; /* PROPERTY signature */
10116 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10123 for (i = 0; i < mono_array_length (fields); ++i) {
10127 field = mono_array_get (fields, gpointer, i);
10128 get_field_name_and_type (field, &fname, &ftype);
10129 *p++ = 0x53; /* FIELD signature */
10130 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10135 g_assert (p - buffer <= buflen);
10136 buflen = p - buffer;
10137 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10138 p = mono_array_addr (result, char, 0);
10139 memcpy (p, buffer, buflen);
10141 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10147 * mono_reflection_setup_internal_class:
10148 * @tb: a TypeBuilder object
10150 * Creates a MonoClass that represents the TypeBuilder.
10151 * This is a trick that lets us simplify a lot of reflection code
10152 * (and will allow us to support Build and Run assemblies easier).
10155 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10158 MonoClass *klass, *parent;
10160 RESOLVE_TYPE (tb->parent);
10162 mono_loader_lock ();
10165 /* check so we can compile corlib correctly */
10166 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10167 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10168 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10170 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10176 /* the type has already being created: it means we just have to change the parent */
10177 if (tb->type.type) {
10178 klass = mono_class_from_mono_type (tb->type.type);
10179 klass->parent = NULL;
10180 /* fool mono_class_setup_parent */
10181 klass->supertypes = NULL;
10182 mono_class_setup_parent (klass, parent);
10183 mono_class_setup_mono_type (klass);
10184 mono_loader_unlock ();
10188 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10190 klass->image = &tb->module->dynamic_image->image;
10192 klass->inited = 1; /* we lie to the runtime */
10193 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10194 if (!mono_error_ok (&error))
10196 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10197 if (!mono_error_ok (&error))
10199 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10200 klass->flags = tb->attrs;
10202 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10204 klass->element_class = klass;
10206 if (mono_class_get_ref_info (klass) == NULL) {
10208 mono_class_set_ref_info (klass, tb);
10210 /* Put into cache so mono_class_get_checked () will find it.
10211 Skip nested types as those should not be available on the global scope. */
10212 if (!tb->nesting_type)
10213 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10216 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10217 by performing a mono_class_get which does the full resolution.
10219 Working around this semantics would require us to write a lot of code for no clear advantage.
10221 mono_image_append_class_to_reflection_info_set (klass);
10223 g_assert (mono_class_get_ref_info (klass) == tb);
10226 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10228 if (parent != NULL) {
10229 mono_class_setup_parent (klass, parent);
10230 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10231 const char *old_n = klass->name;
10232 /* trick to get relative numbering right when compiling corlib */
10233 klass->name = "BuildingObject";
10234 mono_class_setup_parent (klass, mono_defaults.object_class);
10235 klass->name = old_n;
10238 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10239 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10240 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10241 klass->instance_size = sizeof (MonoObject);
10242 klass->size_inited = 1;
10243 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10246 mono_class_setup_mono_type (klass);
10248 mono_class_setup_supertypes (klass);
10251 * FIXME: handle interfaces.
10254 tb->type.type = &klass->byval_arg;
10256 if (tb->nesting_type) {
10257 g_assert (tb->nesting_type->type);
10258 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10261 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10263 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10265 mono_loader_unlock ();
10269 mono_loader_unlock ();
10270 mono_error_raise_exception (&error);
10274 * mono_reflection_setup_generic_class:
10275 * @tb: a TypeBuilder object
10277 * Setup the generic class before adding the first generic parameter.
10280 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10285 * mono_reflection_create_generic_class:
10286 * @tb: a TypeBuilder object
10288 * Creates the generic class after all generic parameters have been added.
10291 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10296 klass = mono_class_from_mono_type (tb->type.type);
10298 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10300 if (klass->generic_container || (count == 0))
10303 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10305 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10307 klass->generic_container->owner.klass = klass;
10308 klass->generic_container->type_argc = count;
10309 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10311 klass->is_generic = 1;
10313 for (i = 0; i < count; i++) {
10314 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10315 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10316 klass->generic_container->type_params [i] = *param;
10317 /*Make sure we are a diferent type instance */
10318 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10319 klass->generic_container->type_params [i].info.pklass = NULL;
10320 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10322 g_assert (klass->generic_container->type_params [i].param.owner);
10325 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10329 * mono_reflection_create_internal_class:
10330 * @tb: a TypeBuilder object
10332 * Actually create the MonoClass that is associated with the TypeBuilder.
10335 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10339 klass = mono_class_from_mono_type (tb->type.type);
10341 mono_loader_lock ();
10342 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10343 MonoReflectionFieldBuilder *fb;
10345 MonoType *enum_basetype;
10347 g_assert (tb->fields != NULL);
10348 g_assert (mono_array_length (tb->fields) >= 1);
10350 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10352 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10353 mono_loader_unlock ();
10357 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10358 klass->element_class = mono_class_from_mono_type (enum_basetype);
10359 if (!klass->element_class)
10360 klass->element_class = mono_class_from_mono_type (enum_basetype);
10363 * get the element_class from the current corlib.
10365 ec = default_class_from_mono_type (enum_basetype);
10366 klass->instance_size = ec->instance_size;
10367 klass->size_inited = 1;
10369 * this is almost safe to do with enums and it's needed to be able
10370 * to create objects of the enum type (for use in SetConstant).
10372 /* FIXME: Does this mean enums can't have method overrides ? */
10373 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10375 mono_loader_unlock ();
10378 static MonoMarshalSpec*
10379 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10380 MonoReflectionMarshal *minfo)
10382 MonoMarshalSpec *res;
10384 res = image_g_new0 (image, MonoMarshalSpec, 1);
10385 res->native = minfo->type;
10387 switch (minfo->type) {
10388 case MONO_NATIVE_LPARRAY:
10389 res->data.array_data.elem_type = minfo->eltype;
10390 if (minfo->has_size) {
10391 res->data.array_data.param_num = minfo->param_num;
10392 res->data.array_data.num_elem = minfo->count;
10393 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10396 res->data.array_data.param_num = -1;
10397 res->data.array_data.num_elem = -1;
10398 res->data.array_data.elem_mult = -1;
10402 case MONO_NATIVE_BYVALTSTR:
10403 case MONO_NATIVE_BYVALARRAY:
10404 res->data.array_data.num_elem = minfo->count;
10407 case MONO_NATIVE_CUSTOM:
10408 if (minfo->marshaltyperef)
10409 res->data.custom_data.custom_name =
10410 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10411 if (minfo->mcookie)
10412 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10421 #endif /* !DISABLE_REFLECTION_EMIT */
10423 MonoReflectionMarshalAsAttribute*
10424 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10425 MonoMarshalSpec *spec)
10427 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10428 MonoReflectionMarshalAsAttribute *minfo;
10431 if (!System_Reflection_Emit_MarshalAsAttribute) {
10432 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10433 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10434 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10437 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10438 minfo->utype = spec->native;
10440 switch (minfo->utype) {
10441 case MONO_NATIVE_LPARRAY:
10442 minfo->array_subtype = spec->data.array_data.elem_type;
10443 minfo->size_const = spec->data.array_data.num_elem;
10444 if (spec->data.array_data.param_num != -1)
10445 minfo->size_param_index = spec->data.array_data.param_num;
10448 case MONO_NATIVE_BYVALTSTR:
10449 case MONO_NATIVE_BYVALARRAY:
10450 minfo->size_const = spec->data.array_data.num_elem;
10453 case MONO_NATIVE_CUSTOM:
10454 if (spec->data.custom_data.custom_name) {
10455 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10457 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10459 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10461 if (spec->data.custom_data.cookie)
10462 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10472 #ifndef DISABLE_REFLECTION_EMIT
10474 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10475 ReflectionMethodBuilder *rmb,
10476 MonoMethodSignature *sig)
10480 MonoMethodWrapper *wrapperm;
10481 MonoMarshalSpec **specs;
10482 MonoReflectionMethodAux *method_aux;
10487 mono_error_init (&error);
10489 * Methods created using a MethodBuilder should have their memory allocated
10490 * inside the image mempool, while dynamic methods should have their memory
10493 dynamic = rmb->refs != NULL;
10494 image = dynamic ? NULL : klass->image;
10497 g_assert (!klass->generic_class);
10499 mono_loader_lock ();
10501 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10502 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10503 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10505 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10507 wrapperm = (MonoMethodWrapper*)m;
10509 m->dynamic = dynamic;
10511 m->flags = rmb->attrs;
10512 m->iflags = rmb->iattrs;
10513 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10515 m->signature = sig;
10516 m->sre_method = TRUE;
10517 m->skip_visibility = rmb->skip_visibility;
10518 if (rmb->table_idx)
10519 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10521 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10522 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10523 m->string_ctor = 1;
10525 m->signature->pinvoke = 1;
10526 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10527 m->signature->pinvoke = 1;
10529 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10531 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10532 g_assert (mono_error_ok (&error));
10533 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10534 g_assert (mono_error_ok (&error));
10536 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10538 if (image_is_dynamic (klass->image))
10539 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10541 mono_loader_unlock ();
10544 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10545 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10546 MonoMethodHeader *header;
10548 gint32 max_stack, i;
10549 gint32 num_locals = 0;
10550 gint32 num_clauses = 0;
10554 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10555 code_size = rmb->ilgen->code_len;
10556 max_stack = rmb->ilgen->max_stack;
10557 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10558 if (rmb->ilgen->ex_handlers)
10559 num_clauses = method_count_clauses (rmb->ilgen);
10562 code = mono_array_addr (rmb->code, guint8, 0);
10563 code_size = mono_array_length (rmb->code);
10564 /* we probably need to run a verifier on the code... */
10574 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10575 header->code_size = code_size;
10576 header->code = image_g_malloc (image, code_size);
10577 memcpy ((char*)header->code, code, code_size);
10578 header->max_stack = max_stack;
10579 header->init_locals = rmb->init_locals;
10580 header->num_locals = num_locals;
10582 for (i = 0; i < num_locals; ++i) {
10583 MonoReflectionLocalBuilder *lb =
10584 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10586 header->locals [i] = image_g_new0 (image, MonoType, 1);
10587 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10590 header->num_clauses = num_clauses;
10592 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10593 rmb->ilgen, num_clauses);
10596 wrapperm->header = header;
10599 if (rmb->generic_params) {
10600 int count = mono_array_length (rmb->generic_params);
10601 MonoGenericContainer *container = rmb->generic_container;
10603 g_assert (container);
10605 container->type_argc = count;
10606 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10607 container->owner.method = m;
10609 m->is_generic = TRUE;
10610 mono_method_set_generic_container (m, container);
10612 for (i = 0; i < count; i++) {
10613 MonoReflectionGenericParam *gp =
10614 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10615 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10616 container->type_params [i] = *param;
10620 * The method signature might have pointers to generic parameters that belong to other methods.
10621 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10622 * generic parameters.
10624 for (i = 0; i < m->signature->param_count; ++i) {
10625 MonoType *t = m->signature->params [i];
10626 if (t->type == MONO_TYPE_MVAR) {
10627 MonoGenericParam *gparam = t->data.generic_param;
10628 if (gparam->num < count) {
10629 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10630 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10636 if (klass->generic_container) {
10637 container->parent = klass->generic_container;
10638 container->context.class_inst = klass->generic_container->context.class_inst;
10640 container->context.method_inst = mono_get_shared_generic_inst (container);
10644 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10648 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10650 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10651 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10652 for (i = 0; i < rmb->nrefs; ++i)
10653 data [i + 1] = rmb->refs [i];
10658 /* Parameter info */
10661 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10662 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10663 for (i = 0; i <= m->signature->param_count; ++i) {
10664 MonoReflectionParamBuilder *pb;
10665 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10666 if ((i > 0) && (pb->attrs)) {
10667 /* Make a copy since it might point to a shared type structure */
10668 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10669 m->signature->params [i - 1]->attrs = pb->attrs;
10672 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10673 MonoDynamicImage *assembly;
10674 guint32 idx, def_type, len;
10678 if (!method_aux->param_defaults) {
10679 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10680 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10682 assembly = (MonoDynamicImage*)klass->image;
10683 idx = encode_constant (assembly, pb->def_value, &def_type);
10684 /* Copy the data from the blob since it might get realloc-ed */
10685 p = assembly->blob.data + idx;
10686 len = mono_metadata_decode_blob_size (p, &p2);
10688 method_aux->param_defaults [i] = image_g_malloc (image, len);
10689 method_aux->param_default_types [i] = def_type;
10690 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10694 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10695 g_assert (mono_error_ok (&error));
10698 if (!method_aux->param_cattr)
10699 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10700 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10706 /* Parameter marshalling */
10709 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10710 MonoReflectionParamBuilder *pb;
10711 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10712 if (pb->marshal_info) {
10714 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10715 specs [pb->position] =
10716 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10720 if (specs != NULL) {
10722 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10723 method_aux->param_marshall = specs;
10726 if (image_is_dynamic (klass->image) && method_aux)
10727 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10729 mono_loader_unlock ();
10735 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10737 ReflectionMethodBuilder rmb;
10738 MonoMethodSignature *sig;
10740 mono_loader_lock ();
10741 sig = ctor_builder_to_signature (klass->image, mb);
10742 mono_loader_unlock ();
10744 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10746 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10747 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10749 /* If we are in a generic class, we might be called multiple times from inflate_method */
10750 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10751 /* ilgen is no longer needed */
10755 return mb->mhandle;
10759 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10761 ReflectionMethodBuilder rmb;
10762 MonoMethodSignature *sig;
10764 mono_loader_lock ();
10765 sig = method_builder_to_signature (klass->image, mb);
10766 mono_loader_unlock ();
10768 reflection_methodbuilder_from_method_builder (&rmb, mb);
10770 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10771 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10773 /* If we are in a generic class, we might be called multiple times from inflate_method */
10774 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10775 /* ilgen is no longer needed */
10778 return mb->mhandle;
10781 static MonoClassField*
10782 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10784 MonoClassField *field;
10788 field = g_new0 (MonoClassField, 1);
10790 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10791 g_assert (mono_error_ok (&error));
10792 if (fb->attrs || fb->modreq || fb->modopt) {
10793 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10794 field->type->attrs = fb->attrs;
10796 g_assert (image_is_dynamic (klass->image));
10797 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10798 g_free (field->type);
10799 field->type = mono_metadata_type_dup (klass->image, custom);
10802 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10804 if (fb->offset != -1)
10805 field->offset = fb->offset;
10806 field->parent = klass;
10807 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10809 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10816 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10819 MonoReflectionTypeBuilder *tb = NULL;
10820 gboolean is_dynamic = FALSE;
10821 MonoClass *geninst;
10823 mono_loader_lock ();
10825 if (is_sre_type_builder (mono_object_class (type))) {
10826 tb = (MonoReflectionTypeBuilder *) type;
10829 } else if (is_sre_generic_instance (mono_object_class (type))) {
10830 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10831 MonoReflectionType *gtd = rgi->generic_type;
10833 if (is_sre_type_builder (mono_object_class (gtd))) {
10834 tb = (MonoReflectionTypeBuilder *)gtd;
10839 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10840 if (tb && tb->generic_container)
10841 mono_reflection_create_generic_class (tb);
10843 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10844 if (!klass->generic_container) {
10845 mono_loader_unlock ();
10849 if (klass->wastypebuilder) {
10850 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10855 mono_loader_unlock ();
10857 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10859 return &geninst->byval_arg;
10863 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10865 MonoGenericClass *gclass;
10866 MonoGenericInst *inst;
10868 g_assert (klass->generic_container);
10870 inst = mono_metadata_get_generic_inst (type_argc, types);
10871 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10873 return mono_generic_class_get_class (gclass);
10876 MonoReflectionMethod*
10877 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10881 MonoMethod *method, *inflated;
10882 MonoMethodInflated *imethod;
10883 MonoGenericContext tmp_context;
10884 MonoGenericInst *ginst;
10885 MonoType **type_argv;
10888 /*FIXME but this no longer should happen*/
10889 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10890 #ifndef DISABLE_REFLECTION_EMIT
10891 MonoReflectionMethodBuilder *mb = NULL;
10892 MonoReflectionTypeBuilder *tb;
10895 mb = (MonoReflectionMethodBuilder *) rmethod;
10896 tb = (MonoReflectionTypeBuilder *) mb->type;
10897 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10899 method = methodbuilder_to_mono_method (klass, mb);
10901 g_assert_not_reached ();
10905 method = rmethod->method;
10908 klass = method->klass;
10910 if (method->is_inflated)
10911 method = ((MonoMethodInflated *) method)->declaring;
10913 count = mono_method_signature (method)->generic_param_count;
10914 if (count != mono_array_length (types))
10917 type_argv = g_new0 (MonoType *, count);
10918 for (i = 0; i < count; i++) {
10919 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10920 type_argv [i] = mono_reflection_type_get_handle (garg);
10922 ginst = mono_metadata_get_generic_inst (count, type_argv);
10923 g_free (type_argv);
10925 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10926 tmp_context.method_inst = ginst;
10928 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10929 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10930 imethod = (MonoMethodInflated *) inflated;
10932 /*FIXME but I think this is no longer necessary*/
10933 if (image_is_dynamic (method->klass->image)) {
10934 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10936 * This table maps metadata structures representing inflated methods/fields
10937 * to the reflection objects representing their generic definitions.
10939 mono_image_lock ((MonoImage*)image);
10940 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10941 mono_image_unlock ((MonoImage*)image);
10944 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10945 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10947 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10950 #ifndef DISABLE_REFLECTION_EMIT
10952 static MonoMethod *
10953 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10955 MonoMethodInflated *imethod;
10956 MonoGenericContext *context;
10960 * With generic code sharing the klass might not be inflated.
10961 * This can happen because classes inflated with their own
10962 * type arguments are "normalized" to the uninflated class.
10964 if (!klass->generic_class)
10967 context = mono_class_get_context (klass);
10969 if (klass->method.count && klass->methods) {
10970 /* Find the already created inflated method */
10971 for (i = 0; i < klass->method.count; ++i) {
10972 g_assert (klass->methods [i]->is_inflated);
10973 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10976 g_assert (i < klass->method.count);
10977 imethod = (MonoMethodInflated*)klass->methods [i];
10980 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10981 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10984 if (method->is_generic && image_is_dynamic (method->klass->image)) {
10985 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10987 mono_image_lock ((MonoImage*)image);
10988 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10989 mono_image_unlock ((MonoImage*)image);
10991 return (MonoMethod *) imethod;
10994 static MonoMethod *
10995 inflate_method (MonoReflectionType *type, MonoObject *obj)
10997 MonoMethod *method;
11000 MonoClass *type_class = mono_object_class (type);
11002 if (is_sre_generic_instance (type_class)) {
11003 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11004 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11005 } else if (is_sre_type_builder (type_class)) {
11006 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11007 } else if (type->type) {
11008 gklass = mono_class_from_mono_type (type->type);
11009 gklass = mono_class_get_generic_type_definition (gklass);
11011 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11014 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11015 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11016 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11018 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11019 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11020 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11021 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11022 method = ((MonoReflectionMethod *) obj)->method;
11024 method = NULL; /* prevent compiler warning */
11025 g_error ("can't handle type %s", obj->vtable->klass->name);
11028 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11031 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11033 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11035 MonoGenericClass *gclass;
11036 MonoDynamicGenericClass *dgclass;
11037 MonoClass *klass, *gklass;
11041 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11042 klass = mono_class_from_mono_type (gtype);
11043 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11044 gclass = gtype->data.generic_class;
11046 if (!gclass->is_dynamic)
11049 dgclass = (MonoDynamicGenericClass *) gclass;
11051 if (dgclass->initialized)
11054 gklass = gclass->container_class;
11055 mono_class_init (gklass);
11057 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11059 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11060 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11061 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11063 for (i = 0; i < dgclass->count_fields; i++) {
11064 MonoObject *obj = mono_array_get (fields, gpointer, i);
11065 MonoClassField *field, *inflated_field = NULL;
11067 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11068 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11069 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11070 field = ((MonoReflectionField *) obj)->field;
11072 field = NULL; /* prevent compiler warning */
11073 g_assert_not_reached ();
11076 dgclass->fields [i] = *field;
11077 dgclass->fields [i].parent = klass;
11078 dgclass->fields [i].type = mono_class_inflate_generic_type (
11079 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11080 dgclass->field_generic_types [i] = field->type;
11081 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11082 dgclass->field_objects [i] = obj;
11084 if (inflated_field) {
11085 g_free (inflated_field);
11087 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11091 dgclass->initialized = TRUE;
11095 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11097 MonoDynamicGenericClass *dgclass;
11100 g_assert (gclass->is_dynamic);
11102 dgclass = (MonoDynamicGenericClass *)gclass;
11104 for (i = 0; i < dgclass->count_fields; ++i) {
11105 MonoClassField *field = dgclass->fields + i;
11106 mono_metadata_free_type (field->type);
11107 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11112 fix_partial_generic_class (MonoClass *klass)
11114 MonoClass *gklass = klass->generic_class->container_class;
11115 MonoDynamicGenericClass *dgclass;
11118 if (klass->wastypebuilder)
11121 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11122 if (klass->parent != gklass->parent) {
11124 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11125 if (mono_error_ok (&error)) {
11126 MonoClass *parent = mono_class_from_mono_type (parent_type);
11127 mono_metadata_free_type (parent_type);
11128 if (parent != klass->parent) {
11129 /*fool mono_class_setup_parent*/
11130 klass->supertypes = NULL;
11131 mono_class_setup_parent (klass, parent);
11134 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11135 mono_error_cleanup (&error);
11136 if (gklass->wastypebuilder)
11137 klass->wastypebuilder = TRUE;
11142 if (!dgclass->initialized)
11145 if (klass->method.count != gklass->method.count) {
11146 klass->method.count = gklass->method.count;
11147 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11149 for (i = 0; i < klass->method.count; i++) {
11151 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11152 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11153 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11157 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11158 klass->interface_count = gklass->interface_count;
11159 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11160 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11162 for (i = 0; i < gklass->interface_count; ++i) {
11163 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11164 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11165 mono_metadata_free_type (iface_type);
11167 ensure_runtime_vtable (klass->interfaces [i]);
11169 klass->interfaces_inited = 1;
11172 if (klass->field.count != gklass->field.count) {
11173 klass->field.count = gklass->field.count;
11174 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11176 for (i = 0; i < klass->field.count; i++) {
11177 klass->fields [i] = gklass->fields [i];
11178 klass->fields [i].parent = klass;
11179 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11183 /*We can only finish with this klass once it's parent has as well*/
11184 if (gklass->wastypebuilder)
11185 klass->wastypebuilder = TRUE;
11190 ensure_generic_class_runtime_vtable (MonoClass *klass)
11192 MonoClass *gklass = klass->generic_class->container_class;
11194 ensure_runtime_vtable (gklass);
11196 fix_partial_generic_class (klass);
11200 ensure_runtime_vtable (MonoClass *klass)
11202 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11205 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11208 ensure_runtime_vtable (klass->parent);
11211 num = tb->ctors? mono_array_length (tb->ctors): 0;
11212 num += tb->num_methods;
11213 klass->method.count = num;
11214 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11215 num = tb->ctors? mono_array_length (tb->ctors): 0;
11216 for (i = 0; i < num; ++i)
11217 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11218 num = tb->num_methods;
11220 for (i = 0; i < num; ++i)
11221 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11223 if (tb->interfaces) {
11224 klass->interface_count = mono_array_length (tb->interfaces);
11225 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11226 for (i = 0; i < klass->interface_count; ++i) {
11227 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11228 klass->interfaces [i] = mono_class_from_mono_type (iface);
11229 ensure_runtime_vtable (klass->interfaces [i]);
11231 klass->interfaces_inited = 1;
11233 } else if (klass->generic_class){
11234 ensure_generic_class_runtime_vtable (klass);
11237 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11239 for (i = 0; i < klass->method.count; ++i) {
11240 MonoMethod *im = klass->methods [i];
11241 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11242 im->slot = slot_num++;
11245 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11246 mono_class_setup_interface_offsets (klass);
11247 mono_class_setup_interface_id (klass);
11251 * The generic vtable is needed even if image->run is not set since some
11252 * runtime code like ves_icall_Type_GetMethodsByName depends on
11253 * method->slot being defined.
11257 * tb->methods could not be freed since it is used for determining
11258 * overrides during dynamic vtable construction.
11263 mono_reflection_method_get_handle (MonoObject *method)
11265 MonoClass *class = mono_object_class (method);
11266 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11267 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11268 return sr_method->method;
11270 if (is_sre_method_builder (class)) {
11271 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11272 return mb->mhandle;
11274 if (is_sre_method_on_tb_inst (class)) {
11275 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11276 MonoMethod *result;
11277 /*FIXME move this to a proper method and unify with resolve_object*/
11278 if (m->method_args) {
11279 result = mono_reflection_method_on_tb_inst_get_handle (m);
11281 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11282 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11283 MonoMethod *mono_method;
11285 if (is_sre_method_builder (mono_object_class (m->mb)))
11286 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11287 else if (is_sr_mono_method (mono_object_class (m->mb)))
11288 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11290 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)));
11292 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11297 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11302 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11304 MonoReflectionTypeBuilder *tb;
11306 MonoReflectionMethod *m;
11309 *num_overrides = 0;
11311 g_assert (image_is_dynamic (klass->image));
11313 if (!mono_class_get_ref_info (klass))
11316 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11318 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11322 for (i = 0; i < tb->num_methods; ++i) {
11323 MonoReflectionMethodBuilder *mb =
11324 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11325 if (mb->override_methods)
11326 onum += mono_array_length (mb->override_methods);
11331 *overrides = g_new0 (MonoMethod*, onum * 2);
11334 for (i = 0; i < tb->num_methods; ++i) {
11335 MonoReflectionMethodBuilder *mb =
11336 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11337 if (mb->override_methods) {
11338 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11339 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11341 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11342 (*overrides) [onum * 2 + 1] = mb->mhandle;
11344 g_assert (mb->mhandle);
11352 *num_overrides = onum;
11356 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11358 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11359 MonoReflectionFieldBuilder *fb;
11360 MonoClassField *field;
11361 MonoImage *image = klass->image;
11362 const char *p, *p2;
11364 guint32 len, idx, real_size = 0;
11366 klass->field.count = tb->num_fields;
11367 klass->field.first = 0;
11369 mono_error_init (error);
11371 if (tb->class_size) {
11372 if ((tb->packing_size & 0xffffff00) != 0) {
11373 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11374 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11377 klass->packing_size = tb->packing_size;
11378 real_size = klass->instance_size + tb->class_size;
11381 if (!klass->field.count) {
11382 klass->instance_size = MAX (klass->instance_size, real_size);
11386 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11387 mono_class_alloc_ext (klass);
11388 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11390 This is, guess what, a hack.
11391 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11392 On the static path no field class is resolved, only types are built. This is the right thing to do
11394 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11396 klass->size_inited = 1;
11398 for (i = 0; i < klass->field.count; ++i) {
11399 MonoArray *rva_data;
11400 fb = mono_array_get (tb->fields, gpointer, i);
11401 field = &klass->fields [i];
11402 field->name = mono_string_to_utf8_image (image, fb->name, error);
11403 if (!mono_error_ok (error))
11406 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11407 field->type->attrs = fb->attrs;
11409 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11412 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11413 char *base = mono_array_addr (rva_data, char, 0);
11414 size_t size = mono_array_length (rva_data);
11415 char *data = mono_image_alloc (klass->image, size);
11416 memcpy (data, base, size);
11417 klass->ext->field_def_values [i].data = data;
11419 if (fb->offset != -1)
11420 field->offset = fb->offset;
11421 field->parent = klass;
11422 fb->handle = field;
11423 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11425 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11426 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11428 if (fb->def_value) {
11429 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11430 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11431 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11432 /* Copy the data from the blob since it might get realloc-ed */
11433 p = assembly->blob.data + idx;
11434 len = mono_metadata_decode_blob_size (p, &p2);
11436 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11437 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11441 klass->instance_size = MAX (klass->instance_size, real_size);
11442 mono_class_layout_fields (klass);
11446 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11448 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11449 MonoReflectionPropertyBuilder *pb;
11450 MonoImage *image = klass->image;
11451 MonoProperty *properties;
11454 mono_error_init (error);
11457 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11459 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11460 klass->ext->property.first = 0;
11462 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11463 klass->ext->properties = properties;
11464 for (i = 0; i < klass->ext->property.count; ++i) {
11465 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11466 properties [i].parent = klass;
11467 properties [i].attrs = pb->attrs;
11468 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11469 if (!mono_error_ok (error))
11471 if (pb->get_method)
11472 properties [i].get = pb->get_method->mhandle;
11473 if (pb->set_method)
11474 properties [i].set = pb->set_method->mhandle;
11476 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11477 if (pb->def_value) {
11479 const char *p, *p2;
11480 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11481 if (!klass->ext->prop_def_values)
11482 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11483 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11484 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11485 /* Copy the data from the blob since it might get realloc-ed */
11486 p = assembly->blob.data + idx;
11487 len = mono_metadata_decode_blob_size (p, &p2);
11489 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11490 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11495 MonoReflectionEvent *
11496 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11498 MonoEvent *event = g_new0 (MonoEvent, 1);
11501 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11503 event->parent = klass;
11504 event->attrs = eb->attrs;
11505 event->name = mono_string_to_utf8 (eb->name);
11506 if (eb->add_method)
11507 event->add = eb->add_method->mhandle;
11508 if (eb->remove_method)
11509 event->remove = eb->remove_method->mhandle;
11510 if (eb->raise_method)
11511 event->raise = eb->raise_method->mhandle;
11513 #ifndef MONO_SMALL_CONFIG
11514 if (eb->other_methods) {
11516 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11517 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11518 MonoReflectionMethodBuilder *mb =
11519 mono_array_get (eb->other_methods,
11520 MonoReflectionMethodBuilder*, j);
11521 event->other [j] = mb->mhandle;
11526 return mono_event_get_object (mono_object_domain (tb), klass, event);
11530 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11532 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11533 MonoReflectionEventBuilder *eb;
11534 MonoImage *image = klass->image;
11538 mono_error_init (error);
11541 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11543 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11544 klass->ext->event.first = 0;
11546 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11547 klass->ext->events = events;
11548 for (i = 0; i < klass->ext->event.count; ++i) {
11549 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11550 events [i].parent = klass;
11551 events [i].attrs = eb->attrs;
11552 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11553 if (!mono_error_ok (error))
11555 if (eb->add_method)
11556 events [i].add = eb->add_method->mhandle;
11557 if (eb->remove_method)
11558 events [i].remove = eb->remove_method->mhandle;
11559 if (eb->raise_method)
11560 events [i].raise = eb->raise_method->mhandle;
11562 #ifndef MONO_SMALL_CONFIG
11563 if (eb->other_methods) {
11565 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11566 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11567 MonoReflectionMethodBuilder *mb =
11568 mono_array_get (eb->other_methods,
11569 MonoReflectionMethodBuilder*, j);
11570 events [i].other [j] = mb->mhandle;
11574 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11579 remove_instantiations_of_and_ensure_contents (gpointer key,
11581 gpointer user_data)
11583 MonoType *type = (MonoType*)key;
11584 MonoClass *klass = (MonoClass*)user_data;
11586 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11587 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11594 check_array_for_usertypes (MonoArray *arr)
11601 for (i = 0; i < mono_array_length (arr); ++i)
11602 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11605 MonoReflectionType*
11606 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11610 MonoDomain* domain;
11611 MonoReflectionType* res;
11614 domain = mono_object_domain (tb);
11615 klass = mono_class_from_mono_type (tb->type.type);
11618 * Check for user defined Type subclasses.
11620 RESOLVE_TYPE (tb->parent);
11621 check_array_for_usertypes (tb->interfaces);
11623 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11624 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11626 RESOLVE_TYPE (fb->type);
11627 check_array_for_usertypes (fb->modreq);
11628 check_array_for_usertypes (fb->modopt);
11629 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11630 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11635 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11636 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11638 RESOLVE_TYPE (mb->rtype);
11639 check_array_for_usertypes (mb->return_modreq);
11640 check_array_for_usertypes (mb->return_modopt);
11641 check_array_for_usertypes (mb->parameters);
11642 if (mb->param_modreq)
11643 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11644 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11645 if (mb->param_modopt)
11646 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11647 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11652 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11653 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11655 check_array_for_usertypes (mb->parameters);
11656 if (mb->param_modreq)
11657 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11658 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11659 if (mb->param_modopt)
11660 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11661 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11666 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11669 * we need to lock the domain because the lock will be taken inside
11670 * So, we need to keep the locking order correct.
11672 mono_loader_lock ();
11673 mono_domain_lock (domain);
11674 if (klass->wastypebuilder) {
11675 mono_domain_unlock (domain);
11676 mono_loader_unlock ();
11677 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11680 * Fields to set in klass:
11681 * the various flags: delegate/unicode/contextbound etc.
11683 klass->flags = tb->attrs;
11684 klass->has_cctor = 1;
11685 klass->has_finalize = 1;
11686 klass->has_finalize_inited = 1;
11688 mono_class_setup_parent (klass, klass->parent);
11689 /* fool mono_class_setup_supertypes */
11690 klass->supertypes = NULL;
11691 mono_class_setup_supertypes (klass);
11692 mono_class_setup_mono_type (klass);
11695 if (!((MonoDynamicImage*)klass->image)->run) {
11696 if (klass->generic_container) {
11697 /* FIXME: The code below can't handle generic classes */
11698 klass->wastypebuilder = TRUE;
11699 mono_loader_unlock ();
11700 mono_domain_unlock (domain);
11701 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11706 /* enums are done right away */
11707 if (!klass->enumtype)
11708 ensure_runtime_vtable (klass);
11710 if (tb->subtypes) {
11711 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11712 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11713 mono_class_alloc_ext (klass);
11714 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)));
11718 klass->nested_classes_inited = TRUE;
11720 /* fields and object layout */
11721 if (klass->parent) {
11722 if (!klass->parent->size_inited)
11723 mono_class_init (klass->parent);
11724 klass->instance_size = klass->parent->instance_size;
11725 klass->sizes.class_size = 0;
11726 klass->min_align = klass->parent->min_align;
11727 /* if the type has no fields we won't call the field_setup
11728 * routine which sets up klass->has_references.
11730 klass->has_references |= klass->parent->has_references;
11732 klass->instance_size = sizeof (MonoObject);
11733 klass->min_align = 1;
11736 /* FIXME: handle packing_size and instance_size */
11737 typebuilder_setup_fields (klass, &error);
11738 if (!mono_error_ok (&error))
11740 typebuilder_setup_properties (klass, &error);
11741 if (!mono_error_ok (&error))
11744 typebuilder_setup_events (klass, &error);
11745 if (!mono_error_ok (&error))
11748 klass->wastypebuilder = TRUE;
11751 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11752 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11753 * we want to return normal System.MonoType objects, so clear these out from the cache.
11755 * Together with this we must ensure the contents of all instances to match the created type.
11757 if (domain->type_hash && klass->generic_container)
11758 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11760 mono_domain_unlock (domain);
11761 mono_loader_unlock ();
11763 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11764 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11765 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11768 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11769 g_assert (res != (MonoReflectionType*)tb);
11774 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11775 klass->wastypebuilder = TRUE;
11776 mono_domain_unlock (domain);
11777 mono_loader_unlock ();
11778 mono_error_raise_exception (&error);
11783 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11785 MonoGenericParamFull *param;
11790 image = &gparam->tbuilder->module->dynamic_image->image;
11792 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11794 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11795 g_assert (mono_error_ok (&error));
11796 param->param.num = gparam->index;
11798 if (gparam->mbuilder) {
11799 if (!gparam->mbuilder->generic_container) {
11800 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11801 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11802 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11803 gparam->mbuilder->generic_container->is_method = TRUE;
11805 * Cannot set owner.method, since the MonoMethod is not created yet.
11806 * Set the image field instead, so type_in_image () works.
11808 gparam->mbuilder->generic_container->image = klass->image;
11810 param->param.owner = gparam->mbuilder->generic_container;
11811 } else if (gparam->tbuilder) {
11812 if (!gparam->tbuilder->generic_container) {
11813 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11814 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11815 gparam->tbuilder->generic_container->owner.klass = klass;
11817 param->param.owner = gparam->tbuilder->generic_container;
11820 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11822 gparam->type.type = &pklass->byval_arg;
11824 mono_class_set_ref_info (pklass, gparam);
11825 mono_image_append_class_to_reflection_info_set (pklass);
11829 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11831 MonoReflectionModuleBuilder *module = sig->module;
11832 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11833 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11838 check_array_for_usertypes (sig->arguments);
11840 sigbuffer_init (&buf, 32);
11842 sigbuffer_add_value (&buf, 0x07);
11843 sigbuffer_add_value (&buf, na);
11844 if (assembly != NULL){
11845 for (i = 0; i < na; ++i) {
11846 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11847 encode_reflection_type (assembly, type, &buf);
11851 buflen = buf.p - buf.buf;
11852 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11853 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11854 sigbuffer_free (&buf);
11860 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11862 MonoDynamicImage *assembly = sig->module->dynamic_image;
11863 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11868 check_array_for_usertypes (sig->arguments);
11870 sigbuffer_init (&buf, 32);
11872 sigbuffer_add_value (&buf, 0x06);
11873 for (i = 0; i < na; ++i) {
11874 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11875 encode_reflection_type (assembly, type, &buf);
11878 buflen = buf.p - buf.buf;
11879 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11880 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11881 sigbuffer_free (&buf);
11887 MonoMethod *handle;
11888 MonoDomain *domain;
11889 } DynamicMethodReleaseData;
11892 * The runtime automatically clean up those after finalization.
11894 static MonoReferenceQueue *dynamic_method_queue;
11897 free_dynamic_method (void *dynamic_method)
11899 DynamicMethodReleaseData *data = dynamic_method;
11900 MonoDomain *domain = data->domain;
11901 MonoMethod *method = data->handle;
11904 mono_domain_lock (domain);
11905 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11906 g_hash_table_remove (domain->method_to_dyn_method, method);
11907 mono_domain_unlock (domain);
11908 g_assert (dis_link);
11909 mono_gchandle_free (dis_link);
11911 mono_runtime_free_method (domain, method);
11916 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11918 MonoReferenceQueue *queue;
11919 MonoMethod *handle;
11920 DynamicMethodReleaseData *release_data;
11921 ReflectionMethodBuilder rmb;
11922 MonoMethodSignature *sig;
11924 MonoDomain *domain;
11928 if (mono_runtime_is_shutting_down ())
11929 mono_raise_exception (mono_get_exception_invalid_operation (""));
11931 if (!(queue = dynamic_method_queue)) {
11932 mono_loader_lock ();
11933 if (!(queue = dynamic_method_queue))
11934 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11935 mono_loader_unlock ();
11938 sig = dynamic_method_to_signature (mb);
11940 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11943 * Resolve references.
11946 * Every second entry in the refs array is reserved for storing handle_class,
11947 * which is needed by the ldtoken implementation in the JIT.
11949 rmb.nrefs = mb->nrefs;
11950 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11951 for (i = 0; i < mb->nrefs; i += 2) {
11952 MonoClass *handle_class;
11954 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11956 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11957 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11959 * The referenced DynamicMethod should already be created by the managed
11960 * code, except in the case of circular references. In that case, we store
11961 * method in the refs array, and fix it up later when the referenced
11962 * DynamicMethod is created.
11964 if (method->mhandle) {
11965 ref = method->mhandle;
11967 /* FIXME: GC object stored in unmanaged memory */
11970 /* FIXME: GC object stored in unmanaged memory */
11971 method->referenced_by = g_slist_append (method->referenced_by, mb);
11973 handle_class = mono_defaults.methodhandle_class;
11975 MonoException *ex = NULL;
11976 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11978 ex = mono_get_exception_type_load (NULL, NULL);
11979 else if (mono_security_core_clr_enabled ())
11980 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11984 mono_raise_exception (ex);
11989 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11990 rmb.refs [i + 1] = handle_class;
11993 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11995 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11996 release_data = g_new (DynamicMethodReleaseData, 1);
11997 release_data->handle = handle;
11998 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11999 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12000 g_free (release_data);
12002 /* Fix up refs entries pointing at us */
12003 for (l = mb->referenced_by; l; l = l->next) {
12004 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12005 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12008 g_assert (method->mhandle);
12010 data = (gpointer*)wrapper->method_data;
12011 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12012 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12013 data [i + 1] = mb->mhandle;
12016 g_slist_free (mb->referenced_by);
12020 /* ilgen is no longer needed */
12023 domain = mono_domain_get ();
12024 mono_domain_lock (domain);
12025 if (!domain->method_to_dyn_method)
12026 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12027 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12028 mono_domain_unlock (domain);
12031 #endif /* DISABLE_REFLECTION_EMIT */
12035 * mono_reflection_is_valid_dynamic_token:
12037 * Returns TRUE if token is valid.
12041 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12043 return lookup_dyn_token (image, token) != NULL;
12046 MonoMethodSignature *
12047 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12049 MonoMethodSignature *sig;
12050 g_assert (image_is_dynamic (image));
12052 mono_error_init (error);
12054 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12058 return mono_method_signature_checked (method, error);
12061 #ifndef DISABLE_REFLECTION_EMIT
12064 * mono_reflection_lookup_dynamic_token:
12066 * Finish the Builder object pointed to by TOKEN and return the corresponding
12067 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12068 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12071 * LOCKING: Take the loader lock
12074 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12076 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12080 obj = lookup_dyn_token (assembly, token);
12083 g_error ("Could not find required dynamic token 0x%08x", token);
12089 handle_class = &klass;
12090 return resolve_object (image, obj, handle_class, context);
12094 * ensure_complete_type:
12096 * Ensure that KLASS is completed if it is a dynamic type, or references
12100 ensure_complete_type (MonoClass *klass)
12102 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12103 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12105 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12107 // Asserting here could break a lot of code
12108 //g_assert (klass->wastypebuilder);
12111 if (klass->generic_class) {
12112 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12115 for (i = 0; i < inst->type_argc; ++i) {
12116 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12122 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12124 gpointer result = NULL;
12126 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12127 result = mono_string_intern ((MonoString*)obj);
12128 *handle_class = mono_defaults.string_class;
12130 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12131 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12132 MonoClass *mc = mono_class_from_mono_type (type);
12133 if (!mono_class_init (mc))
12134 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12137 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12138 result = mono_class_from_mono_type (inflated);
12139 mono_metadata_free_type (inflated);
12141 result = mono_class_from_mono_type (type);
12143 *handle_class = mono_defaults.typehandle_class;
12145 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12146 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12147 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12148 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12149 result = ((MonoReflectionMethod*)obj)->method;
12152 result = mono_class_inflate_generic_method_checked (result, context, &error);
12153 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12155 *handle_class = mono_defaults.methodhandle_class;
12157 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12158 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12159 result = mb->mhandle;
12161 /* Type is not yet created */
12162 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12164 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12167 * Hopefully this has been filled in by calling CreateType() on the
12171 * TODO: This won't work if the application finishes another
12172 * TypeBuilder instance instead of this one.
12174 result = mb->mhandle;
12178 result = mono_class_inflate_generic_method_checked (result, context, &error);
12179 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12181 *handle_class = mono_defaults.methodhandle_class;
12182 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12183 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12185 result = cb->mhandle;
12187 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12189 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12190 result = cb->mhandle;
12194 result = mono_class_inflate_generic_method_checked (result, context, &error);
12195 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12197 *handle_class = mono_defaults.methodhandle_class;
12198 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12199 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12201 ensure_complete_type (field->parent);
12203 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12204 MonoClass *class = mono_class_from_mono_type (inflated);
12205 MonoClassField *inflated_field;
12206 gpointer iter = NULL;
12207 mono_metadata_free_type (inflated);
12208 while ((inflated_field = mono_class_get_fields (class, &iter))) {
12209 if (!strcmp (field->name, inflated_field->name))
12212 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12213 result = inflated_field;
12217 *handle_class = mono_defaults.fieldhandle_class;
12219 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12220 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12221 result = fb->handle;
12224 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12226 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12227 result = fb->handle;
12230 if (fb->handle && fb->handle->parent->generic_container) {
12231 MonoClass *klass = fb->handle->parent;
12232 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12233 MonoClass *inflated = mono_class_from_mono_type (type);
12235 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12237 mono_metadata_free_type (type);
12239 *handle_class = mono_defaults.fieldhandle_class;
12240 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12241 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12242 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12245 klass = type->data.klass;
12246 if (klass->wastypebuilder) {
12247 /* Already created */
12251 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12252 result = type->data.klass;
12255 *handle_class = mono_defaults.typehandle_class;
12256 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12257 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12258 MonoMethodSignature *sig;
12261 if (helper->arguments)
12262 nargs = mono_array_length (helper->arguments);
12266 sig = mono_metadata_signature_alloc (image, nargs);
12267 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12268 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12270 if (helper->unmanaged_call_conv) { /* unmanaged */
12271 sig->call_convention = helper->unmanaged_call_conv - 1;
12272 sig->pinvoke = TRUE;
12273 } else if (helper->call_conv & 0x02) {
12274 sig->call_convention = MONO_CALL_VARARG;
12276 sig->call_convention = MONO_CALL_DEFAULT;
12279 sig->param_count = nargs;
12280 /* TODO: Copy type ? */
12281 sig->ret = helper->return_type->type;
12282 for (i = 0; i < nargs; ++i)
12283 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12286 *handle_class = NULL;
12287 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12288 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12289 /* Already created by the managed code */
12290 g_assert (method->mhandle);
12291 result = method->mhandle;
12292 *handle_class = mono_defaults.methodhandle_class;
12293 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12294 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12295 type = mono_class_inflate_generic_type (type, context);
12296 result = mono_class_from_mono_type (type);
12297 *handle_class = mono_defaults.typehandle_class;
12299 mono_metadata_free_type (type);
12300 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12301 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12302 type = mono_class_inflate_generic_type (type, context);
12303 result = mono_class_from_mono_type (type);
12304 *handle_class = mono_defaults.typehandle_class;
12306 mono_metadata_free_type (type);
12307 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12308 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12309 MonoClass *inflated;
12311 MonoClassField *field;
12313 if (is_sre_field_builder (mono_object_class (f->fb)))
12314 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12315 else if (is_sr_mono_field (mono_object_class (f->fb)))
12316 field = ((MonoReflectionField*)f->fb)->field;
12318 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)));
12320 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12321 inflated = mono_class_from_mono_type (type);
12323 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12324 ensure_complete_type (field->parent);
12326 mono_metadata_free_type (type);
12327 *handle_class = mono_defaults.fieldhandle_class;
12328 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12329 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12330 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12331 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12332 MonoMethod *method;
12334 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12335 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12336 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12337 method = ((MonoReflectionMethod *)c->cb)->method;
12339 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)));
12341 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12342 *handle_class = mono_defaults.methodhandle_class;
12343 mono_metadata_free_type (type);
12344 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12345 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12346 if (m->method_args) {
12347 result = mono_reflection_method_on_tb_inst_get_handle (m);
12350 result = mono_class_inflate_generic_method_checked (result, context, &error);
12351 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12354 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12355 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12356 MonoMethod *method;
12358 if (is_sre_method_builder (mono_object_class (m->mb)))
12359 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12360 else if (is_sr_mono_method (mono_object_class (m->mb)))
12361 method = ((MonoReflectionMethod *)m->mb)->method;
12363 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)));
12365 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12366 mono_metadata_free_type (type);
12368 *handle_class = mono_defaults.methodhandle_class;
12369 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12370 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12373 MonoMethod *method;
12377 mtype = mono_reflection_type_get_handle (m->parent);
12378 klass = mono_class_from_mono_type (mtype);
12380 /* Find the method */
12382 name = mono_string_to_utf8 (m->name);
12384 while ((method = mono_class_get_methods (klass, &iter))) {
12385 if (!strcmp (method->name, name))
12392 // FIXME: Check parameters/return value etc. match
12395 *handle_class = mono_defaults.methodhandle_class;
12396 } else if (is_sre_array (mono_object_get_class(obj)) ||
12397 is_sre_byref (mono_object_get_class(obj)) ||
12398 is_sre_pointer (mono_object_get_class(obj))) {
12399 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12400 MonoType *type = mono_reflection_type_get_handle (ref_type);
12403 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12404 result = mono_class_from_mono_type (inflated);
12405 mono_metadata_free_type (inflated);
12407 result = mono_class_from_mono_type (type);
12409 *handle_class = mono_defaults.typehandle_class;
12411 g_print ("%s\n", obj->vtable->klass->name);
12412 g_assert_not_reached ();
12417 #else /* DISABLE_REFLECTION_EMIT */
12420 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12422 g_assert_not_reached ();
12427 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12429 g_assert_not_reached ();
12433 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12435 g_assert_not_reached ();
12439 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12441 g_assert_not_reached ();
12445 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12447 g_assert_not_reached ();
12451 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12453 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12457 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12459 g_assert_not_reached ();
12463 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12465 g_assert_not_reached ();
12468 MonoReflectionModule *
12469 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12471 g_assert_not_reached ();
12476 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12478 g_assert_not_reached ();
12483 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12485 g_assert_not_reached ();
12490 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12491 gboolean create_open_instance, gboolean register_token)
12493 g_assert_not_reached ();
12498 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12503 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12505 g_assert_not_reached ();
12509 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12512 *num_overrides = 0;
12515 MonoReflectionEvent *
12516 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12518 g_assert_not_reached ();
12522 MonoReflectionType*
12523 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12525 g_assert_not_reached ();
12530 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12532 g_assert_not_reached ();
12536 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12538 g_assert_not_reached ();
12543 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12545 g_assert_not_reached ();
12550 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12555 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12561 mono_reflection_type_get_handle (MonoReflectionType* ref)
12569 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12571 g_assert_not_reached ();
12574 #endif /* DISABLE_REFLECTION_EMIT */
12576 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12577 const static guint32 declsec_flags_map[] = {
12578 0x00000000, /* empty */
12579 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12580 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12581 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12582 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12583 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12584 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12585 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12586 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12587 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12588 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12589 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12590 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12591 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12592 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12593 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12594 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12595 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12596 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12600 * Returns flags that includes all available security action associated to the handle.
12601 * @token: metadata token (either for a class or a method)
12602 * @image: image where resides the metadata.
12605 mono_declsec_get_flags (MonoImage *image, guint32 token)
12607 int index = mono_metadata_declsec_from_index (image, token);
12608 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12609 guint32 result = 0;
12613 /* HasSecurity can be present for other, not specially encoded, attributes,
12614 e.g. SuppressUnmanagedCodeSecurityAttribute */
12618 for (i = index; i < t->rows; i++) {
12619 guint32 cols [MONO_DECL_SECURITY_SIZE];
12621 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12622 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12625 action = cols [MONO_DECL_SECURITY_ACTION];
12626 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12627 result |= declsec_flags_map [action];
12629 g_assert_not_reached ();
12636 * Get the security actions (in the form of flags) associated with the specified method.
12638 * @method: The method for which we want the declarative security flags.
12639 * Return the declarative security flags for the method (only).
12641 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12642 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12645 mono_declsec_flags_from_method (MonoMethod *method)
12647 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12648 /* FIXME: No cache (for the moment) */
12649 guint32 idx = mono_method_get_index (method);
12650 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12651 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12652 return mono_declsec_get_flags (method->klass->image, idx);
12658 * Get the security actions (in the form of flags) associated with the specified class.
12660 * @klass: The class for which we want the declarative security flags.
12661 * Return the declarative security flags for the class.
12663 * Note: We cache the flags inside the MonoClass structure as this will get
12664 * called very often (at least for each method).
12667 mono_declsec_flags_from_class (MonoClass *klass)
12669 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12670 if (!klass->ext || !klass->ext->declsec_flags) {
12673 idx = mono_metadata_token_index (klass->type_token);
12674 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12675 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12676 mono_loader_lock ();
12677 mono_class_alloc_ext (klass);
12678 mono_loader_unlock ();
12679 /* we cache the flags on classes */
12680 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12682 return klass->ext->declsec_flags;
12688 * Get the security actions (in the form of flags) associated with the specified assembly.
12690 * @assembly: The assembly for which we want the declarative security flags.
12691 * Return the declarative security flags for the assembly.
12694 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12696 guint32 idx = 1; /* there is only one assembly */
12697 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12698 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12699 return mono_declsec_get_flags (assembly->image, idx);
12704 * Fill actions for the specific index (which may either be an encoded class token or
12705 * an encoded method token) from the metadata image.
12706 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12709 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12710 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12712 MonoBoolean result = FALSE;
12714 guint32 cols [MONO_DECL_SECURITY_SIZE];
12715 int index = mono_metadata_declsec_from_index (image, token);
12718 t = &image->tables [MONO_TABLE_DECLSECURITY];
12719 for (i = index; i < t->rows; i++) {
12720 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12722 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12725 /* if present only replace (class) permissions with method permissions */
12726 /* if empty accept either class or method permissions */
12727 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12728 if (!actions->demand.blob) {
12729 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12730 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12731 actions->demand.blob = (char*) (blob + 2);
12732 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12735 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12736 if (!actions->noncasdemand.blob) {
12737 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12738 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12739 actions->noncasdemand.blob = (char*) (blob + 2);
12740 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12743 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12744 if (!actions->demandchoice.blob) {
12745 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12746 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12747 actions->demandchoice.blob = (char*) (blob + 2);
12748 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12758 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12759 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12761 guint32 idx = mono_metadata_token_index (klass->type_token);
12762 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12763 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12764 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12768 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12769 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12771 guint32 idx = mono_method_get_index (method);
12772 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12773 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12774 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12778 * Collect all actions (that requires to generate code in mini) assigned for
12779 * the specified method.
12780 * Note: Don't use the content of actions if the function return FALSE.
12783 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12785 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12786 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12787 MonoBoolean result = FALSE;
12790 /* quick exit if no declarative security is present in the metadata */
12791 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12794 /* we want the original as the wrapper is "free" of the security informations */
12795 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12796 method = mono_marshal_method_from_wrapper (method);
12801 /* First we look for method-level attributes */
12802 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12803 mono_class_init (method->klass);
12804 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12806 result = mono_declsec_get_method_demands_params (method, demands,
12807 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12810 /* Here we use (or create) the class declarative cache to look for demands */
12811 flags = mono_declsec_flags_from_class (method->klass);
12812 if (flags & mask) {
12814 mono_class_init (method->klass);
12815 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12817 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12818 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12821 /* The boolean return value is used as a shortcut in case nothing needs to
12822 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12828 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12830 * Note: Don't use the content of actions if the function return FALSE.
12833 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12835 MonoBoolean result = FALSE;
12838 /* quick exit if no declarative security is present in the metadata */
12839 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12842 /* we want the original as the wrapper is "free" of the security informations */
12843 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12844 method = mono_marshal_method_from_wrapper (method);
12849 /* results are independant - zeroize both */
12850 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12851 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12853 /* First we look for method-level attributes */
12854 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12855 mono_class_init (method->klass);
12857 result = mono_declsec_get_method_demands_params (method, cmethod,
12858 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12861 /* Here we use (or create) the class declarative cache to look for demands */
12862 flags = mono_declsec_flags_from_class (method->klass);
12863 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12864 mono_class_init (method->klass);
12866 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12867 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12874 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12876 * @klass The inherited class - this is the class that provides the security check (attributes)
12878 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12880 * Note: Don't use the content of actions if the function return FALSE.
12883 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12885 MonoBoolean result = FALSE;
12888 /* quick exit if no declarative security is present in the metadata */
12889 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12892 /* Here we use (or create) the class declarative cache to look for demands */
12893 flags = mono_declsec_flags_from_class (klass);
12894 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12895 mono_class_init (klass);
12896 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12898 result |= mono_declsec_get_class_demands_params (klass, demands,
12899 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12906 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12908 * Note: Don't use the content of actions if the function return FALSE.
12911 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12913 /* quick exit if no declarative security is present in the metadata */
12914 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12917 /* we want the original as the wrapper is "free" of the security informations */
12918 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12919 method = mono_marshal_method_from_wrapper (method);
12924 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12925 mono_class_init (method->klass);
12926 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12928 return mono_declsec_get_method_demands_params (method, demands,
12929 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12936 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12938 guint32 cols [MONO_DECL_SECURITY_SIZE];
12942 int index = mono_metadata_declsec_from_index (image, token);
12946 t = &image->tables [MONO_TABLE_DECLSECURITY];
12947 for (i = index; i < t->rows; i++) {
12948 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12950 /* shortcut - index are ordered */
12951 if (token != cols [MONO_DECL_SECURITY_PARENT])
12954 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12955 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12956 entry->blob = (char*) (metadata + 2);
12957 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12966 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12968 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12969 guint32 idx = mono_method_get_index (method);
12970 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12971 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12972 return get_declsec_action (method->klass->image, idx, action, entry);
12978 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12981 guint32 flags = mono_declsec_flags_from_class (klass);
12982 if (declsec_flags_map [action] & flags) {
12983 guint32 idx = mono_metadata_token_index (klass->type_token);
12984 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12985 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12986 return get_declsec_action (klass->image, idx, action, entry);
12992 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12994 guint32 idx = 1; /* there is only one assembly */
12995 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12996 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12998 return get_declsec_action (assembly->image, idx, action, entry);
13002 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13004 MonoObject *res, *exc;
13006 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13007 static MonoMethod *method = NULL;
13009 if (!System_Reflection_Emit_TypeBuilder) {
13010 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13011 g_assert (System_Reflection_Emit_TypeBuilder);
13013 if (method == NULL) {
13014 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13019 * The result of mono_type_get_object () might be a System.MonoType but we
13020 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13022 g_assert (mono_class_get_ref_info (klass));
13023 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13025 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13027 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13031 return *(MonoBoolean*)mono_object_unbox (res);
13035 * mono_reflection_type_get_type:
13036 * @reftype: the System.Type object
13038 * Returns the MonoType* associated with the C# System.Type object @reftype.
13041 mono_reflection_type_get_type (MonoReflectionType *reftype)
13043 g_assert (reftype);
13045 return mono_reflection_type_get_handle (reftype);
13049 * mono_reflection_assembly_get_assembly:
13050 * @refassembly: the System.Reflection.Assembly object
13052 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13055 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13057 g_assert (refassembly);
13059 return refassembly->assembly;