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 *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
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 *klass = 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, &klass->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 klass = 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 (klass->generic_container)
1901 typespec = create_typespec (assembly, type);
1904 MonoGenericClass *gclass;
1905 gclass = mono_metadata_lookup_generic_class (klass, klass->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 *klass, *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 klass = field->parent;
2912 gtd = klass->generic_class->container_class;
2914 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2915 field_index = field - klass->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 *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6442 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6444 assembly_type = klass;
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 *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6465 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6467 module_type = klass;
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 *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6512 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6514 module_type = klass;
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->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7123 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7126 image = method->klass->image;
7127 header = mono_method_get_header (method);
7129 if (!image_is_dynamic (image)) {
7130 /* Obtain local vars signature token */
7131 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7132 ptr = mono_image_rva_map (image, method_rva);
7133 flags = *(const unsigned char *) ptr;
7134 format = flags & METHOD_HEADER_FORMAT_MASK;
7136 case METHOD_HEADER_TINY_FORMAT:
7137 local_var_sig_token = 0;
7139 case METHOD_HEADER_FAT_FORMAT:
7143 local_var_sig_token = read32 (ptr);
7146 g_assert_not_reached ();
7149 local_var_sig_token = 0; //FIXME
7151 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7153 ret->init_locals = header->init_locals;
7154 ret->max_stack = header->max_stack;
7155 ret->local_var_sig_token = local_var_sig_token;
7156 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7157 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7160 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7161 for (i = 0; i < header->num_locals; ++i) {
7162 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7163 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7164 info->is_pinned = header->locals [i]->pinned;
7165 info->local_index = i;
7166 mono_array_setref (ret->locals, i, info);
7170 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7171 for (i = 0; i < header->num_clauses; ++i) {
7172 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7173 MonoExceptionClause *clause = &header->clauses [i];
7175 info->flags = clause->flags;
7176 info->try_offset = clause->try_offset;
7177 info->try_length = clause->try_len;
7178 info->handler_offset = clause->handler_offset;
7179 info->handler_length = clause->handler_len;
7180 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7181 info->filter_offset = clause->data.filter_offset;
7182 else if (clause->data.catch_class)
7183 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7185 mono_array_setref (ret->clauses, i, info);
7188 mono_metadata_free_mh (header);
7189 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7194 * mono_get_dbnull_object:
7195 * @domain: Domain where the object lives
7197 * Returns the System.DBNull.Value singleton object
7199 * Used as the value for ParameterInfo.DefaultValue
7202 mono_get_dbnull_object (MonoDomain *domain)
7205 static MonoClassField *dbnull_value_field = NULL;
7207 if (!dbnull_value_field) {
7208 MonoClass *dbnull_klass;
7209 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7210 mono_class_init (dbnull_klass);
7211 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7212 g_assert (dbnull_value_field);
7214 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7220 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7222 guint32 param_index, i, lastp, crow = 0;
7223 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7226 MonoClass *klass = method->klass;
7227 MonoImage *image = klass->image;
7228 MonoMethodSignature *methodsig = mono_method_signature (method);
7230 MonoTableInfo *constt;
7231 MonoTableInfo *methodt;
7232 MonoTableInfo *paramt;
7234 if (!methodsig->param_count)
7237 mono_class_init (klass);
7239 if (image_is_dynamic (klass->image)) {
7240 MonoReflectionMethodAux *aux;
7241 if (method->is_inflated)
7242 method = ((MonoMethodInflated*)method)->declaring;
7243 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7244 if (aux && aux->param_defaults) {
7245 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7246 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7251 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7252 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7253 constt = &image->tables [MONO_TABLE_CONSTANT];
7255 idx = mono_method_get_index (method) - 1;
7256 g_assert (idx != -1);
7258 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7259 if (idx + 1 < methodt->rows)
7260 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7262 lastp = paramt->rows + 1;
7264 for (i = param_index; i < lastp; ++i) {
7267 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7268 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7270 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7273 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7278 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7279 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7280 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7287 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7292 MonoType *basetype = type;
7297 klass = mono_class_from_mono_type (type);
7298 if (klass->valuetype) {
7299 object = mono_object_new (domain, klass);
7300 retval = ((gchar *) object + sizeof (MonoObject));
7301 if (klass->enumtype)
7302 basetype = mono_class_enum_basetype (klass);
7307 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7314 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7317 gboolean quoted = FALSE;
7319 memset (assembly, 0, sizeof (MonoAssemblyName));
7320 assembly->culture = "";
7321 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7328 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7339 /* Remove trailing whitespace */
7341 while (*s && g_ascii_isspace (*s))
7344 while (g_ascii_isspace (*p))
7347 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7349 assembly->major = strtoul (p, &s, 10);
7350 if (s == p || *s != '.')
7353 assembly->minor = strtoul (p, &s, 10);
7354 if (s == p || *s != '.')
7357 assembly->build = strtoul (p, &s, 10);
7358 if (s == p || *s != '.')
7361 assembly->revision = strtoul (p, &s, 10);
7365 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7367 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7368 assembly->culture = "";
7371 assembly->culture = p;
7372 while (*p && *p != ',') {
7376 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7378 if (strncmp (p, "null", 4) == 0) {
7383 while (*p && *p != ',') {
7386 len = (p - start + 1);
7387 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7388 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7389 g_strlcpy ((char*)assembly->public_key_token, start, len);
7392 while (*p && *p != ',')
7396 while (g_ascii_isspace (*p) || *p == ',') {
7410 * mono_reflection_parse_type:
7413 * Parse a type name as accepted by the GetType () method and output the info
7414 * extracted in the info structure.
7415 * the name param will be mangled, so, make a copy before passing it to this function.
7416 * The fields in info will be valid until the memory pointed to by name is valid.
7418 * See also mono_type_get_name () below.
7420 * Returns: 0 on parse error.
7423 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7424 MonoTypeNameParse *info)
7426 char *start, *p, *w, *last_point, *startn;
7427 int in_modifiers = 0;
7428 int isbyref = 0, rank = 0, isptr = 0;
7430 start = p = w = name;
7432 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7433 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7434 info->name = info->name_space = NULL;
7435 info->nested = NULL;
7436 info->modifiers = NULL;
7437 info->type_arguments = NULL;
7439 /* last_point separates the namespace from the name */
7442 while (*p == ' ') p++, start++, w++, name++;
7447 *p = 0; /* NULL terminate the name */
7449 info->nested = g_list_append (info->nested, startn);
7450 /* we have parsed the nesting namespace + name */
7454 info->name_space = start;
7456 info->name = last_point + 1;
7458 info->name_space = (char *)"";
7486 info->name_space = start;
7488 info->name = last_point + 1;
7490 info->name_space = (char *)"";
7497 if (isbyref) /* only one level allowed by the spec */
7501 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7505 if (isbyref) /* pointer to ref not okay */
7507 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7512 if (isbyref) /* array of ref and generic ref are not okay */
7514 //Decide if it's an array of a generic argument list
7519 if (*p == ',' || *p == '*' || *p == ']') { //array
7527 else if (*p == '*') /* '*' means unknown lower bound */
7528 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7535 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7537 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7540 info->type_arguments = g_ptr_array_new ();
7542 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7543 gboolean fqname = FALSE;
7545 g_ptr_array_add (info->type_arguments, subinfo);
7547 while (*p == ' ') p++;
7553 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7556 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7557 if (fqname && (*p != ']')) {
7565 while (*p && (*p != ']'))
7573 if (g_ascii_isspace (*aname)) {
7580 !assembly_name_to_aname (&subinfo->assembly, aname))
7582 } else if (fqname && (*p == ']')) {
7604 if (g_ascii_isspace (*p)) {
7611 return 0; /* missing assembly name */
7612 if (!assembly_name_to_aname (&info->assembly, p))
7618 if (info->assembly.name)
7621 // *w = 0; /* terminate class name */
7623 if (!info->name || !*info->name)
7627 /* add other consistency checks */
7633 * mono_identifier_unescape_type_name_chars:
7634 * @identifier: the display name of a mono type
7637 * The name in internal form, that is without escaping backslashes.
7639 * The string is modified in place!
7642 mono_identifier_unescape_type_name_chars(char* identifier)
7647 for (w = r = identifier; *r != 0; r++)
7665 mono_identifier_unescape_info (MonoTypeNameParse* info);
7668 unescape_each_type_argument(void* data, void* user_data)
7670 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7671 mono_identifier_unescape_info (info);
7675 unescape_each_nested_name (void* data, void* user_data)
7677 char* nested_name = (char*) data;
7678 mono_identifier_unescape_type_name_chars(nested_name);
7682 * mono_identifier_unescape_info:
7684 * @info: a parsed display form of an (optionally assembly qualified) full type name.
7688 * Destructively updates the info by unescaping the identifiers that
7689 * comprise the type namespace, name, nested types (if any) and
7690 * generic type arguments (if any).
7692 * The resulting info has the names in internal form.
7696 mono_identifier_unescape_info (MonoTypeNameParse *info)
7700 mono_identifier_unescape_type_name_chars(info->name_space);
7701 mono_identifier_unescape_type_name_chars(info->name);
7702 // but don't escape info->assembly
7703 if (info->type_arguments)
7704 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7706 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7710 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7712 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7714 mono_identifier_unescape_info (info);
7720 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7722 gboolean type_resolve = FALSE;
7724 MonoImage *rootimage = image;
7726 if (info->assembly.name) {
7727 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7728 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7730 * This could happen in the AOT compiler case when the search hook is not
7733 assembly = image->assembly;
7735 /* then we must load the assembly ourselve - see #60439 */
7736 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7740 image = assembly->image;
7741 } else if (!image) {
7742 image = mono_defaults.corlib;
7745 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7746 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7747 image = mono_defaults.corlib;
7748 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7755 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7760 gboolean bounded = FALSE;
7763 image = mono_defaults.corlib;
7766 rootimage = mono_defaults.corlib;
7770 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7771 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7773 klass = mono_class_from_name (image, info->name_space, info->name);
7777 for (mod = info->nested; mod; mod = mod->next) {
7778 gpointer iter = NULL;
7782 mono_class_init (parent);
7784 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7786 char *nested_name, *nested_nspace;
7787 gboolean match = TRUE;
7789 lastp = strrchr (mod->data, '.');
7791 /* Nested classes can have namespaces */
7794 nested_name = g_strdup (lastp + 1);
7795 nspace_len = lastp - (char*)mod->data;
7796 nested_nspace = g_malloc (nspace_len + 1);
7797 memcpy (nested_nspace, mod->data, nspace_len);
7798 nested_nspace [nspace_len] = '\0';
7801 nested_name = mod->data;
7802 nested_nspace = NULL;
7805 if (nested_nspace) {
7807 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7810 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7816 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7819 if (strcmp (klass->name, nested_name) != 0)
7824 g_free (nested_name);
7825 g_free (nested_nspace);
7837 if (info->type_arguments) {
7838 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7839 MonoReflectionType *the_type;
7843 for (i = 0; i < info->type_arguments->len; i++) {
7844 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7846 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7847 if (!type_args [i]) {
7853 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7855 instance = mono_reflection_bind_generic_parameters (
7856 the_type, info->type_arguments->len, type_args);
7862 klass = mono_class_from_mono_type (instance);
7865 for (mod = info->modifiers; mod; mod = mod->next) {
7866 modval = GPOINTER_TO_UINT (mod->data);
7867 if (!modval) { /* byref: must be last modifier */
7868 return &klass->this_arg;
7869 } else if (modval == -1) {
7870 klass = mono_ptr_class_get (&klass->byval_arg);
7871 } else if (modval == -2) {
7873 } else { /* array rank */
7874 klass = mono_bounded_array_class_get (klass, modval, bounded);
7878 return &klass->byval_arg;
7882 * mono_reflection_get_type:
7883 * @image: a metadata context
7884 * @info: type description structure
7885 * @ignorecase: flag for case-insensitive string compares
7886 * @type_resolve: whenever type resolve was already tried
7888 * Build a MonoType from the type description in @info.
7893 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7894 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7898 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7900 MonoReflectionAssemblyBuilder *abuilder;
7904 g_assert (assembly_is_dynamic (assembly));
7905 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7907 /* Enumerate all modules */
7910 if (abuilder->modules) {
7911 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7912 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7913 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7919 if (!type && abuilder->loaded_modules) {
7920 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7921 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7922 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7932 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7935 MonoReflectionAssembly *assembly;
7939 if (image && image_is_dynamic (image))
7940 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7942 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7945 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7952 *type_resolve = TRUE;
7955 /* Reconstruct the type name */
7956 fullName = g_string_new ("");
7957 if (info->name_space && (info->name_space [0] != '\0'))
7958 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7960 g_string_printf (fullName, "%s", info->name);
7961 for (mod = info->nested; mod; mod = mod->next)
7962 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7964 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7966 if (assembly_is_dynamic (assembly->assembly))
7967 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7969 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7972 g_string_free (fullName, TRUE);
7977 mono_reflection_free_type_info (MonoTypeNameParse *info)
7979 g_list_free (info->modifiers);
7980 g_list_free (info->nested);
7982 if (info->type_arguments) {
7985 for (i = 0; i < info->type_arguments->len; i++) {
7986 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7988 mono_reflection_free_type_info (subinfo);
7989 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7993 g_ptr_array_free (info->type_arguments, TRUE);
7998 * mono_reflection_type_from_name:
8000 * @image: a metadata context (can be NULL).
8002 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8003 * it defaults to get the type from @image or, if @image is NULL or loading
8004 * from it fails, uses corlib.
8008 mono_reflection_type_from_name (char *name, MonoImage *image)
8010 MonoType *type = NULL;
8011 MonoTypeNameParse info;
8014 /* Make a copy since parse_type modifies its argument */
8015 tmp = g_strdup (name);
8017 /*g_print ("requested type %s\n", str);*/
8018 if (mono_reflection_parse_type (tmp, &info)) {
8019 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8023 mono_reflection_free_type_info (&info);
8028 * mono_reflection_get_token:
8030 * Return the metadata token of OBJ which should be an object
8031 * representing a metadata element.
8034 mono_reflection_get_token (MonoObject *obj)
8039 klass = obj->vtable->klass;
8041 if (strcmp (klass->name, "MethodBuilder") == 0) {
8042 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8044 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8045 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8046 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8048 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8049 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8050 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8052 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8053 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8054 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8055 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8056 } else if (strcmp (klass->name, "MonoType") == 0) {
8057 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8058 MonoClass *mc = mono_class_from_mono_type (type);
8059 if (!mono_class_init (mc))
8060 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8062 token = mc->type_token;
8063 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8064 strcmp (klass->name, "MonoMethod") == 0 ||
8065 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8066 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8067 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8068 if (m->method->is_inflated) {
8069 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8070 return inflated->declaring->token;
8072 token = m->method->token;
8074 } else if (strcmp (klass->name, "MonoField") == 0) {
8075 MonoReflectionField *f = (MonoReflectionField*)obj;
8077 if (is_field_on_inst (f->field)) {
8078 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8080 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8081 int field_index = f->field - dgclass->fields;
8084 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8085 obj = dgclass->field_objects [field_index];
8086 return mono_reflection_get_token (obj);
8089 token = mono_class_get_field_token (f->field);
8090 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8091 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8093 token = mono_class_get_property_token (p->property);
8094 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8095 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8097 token = mono_class_get_event_token (p->event);
8098 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8099 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8100 MonoClass *member_class = mono_object_class (p->MemberImpl);
8101 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8103 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8104 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8105 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8108 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8109 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8111 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8112 MonoException *ex = mono_get_exception_not_implemented (msg);
8114 mono_raise_exception (ex);
8121 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8125 int slen = mono_metadata_decode_value (p, &p);
8127 mono_error_init (error);
8129 n = g_memdup (p, slen + 1);
8131 t = mono_reflection_type_from_name (n, image);
8133 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8134 /* We don't free n, it's consumed by mono_error */
8135 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8141 return mono_class_from_mono_type (t);
8145 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8147 int slen, type = t->type;
8148 MonoClass *tklass = t->data.klass;
8150 mono_error_init (error);
8156 case MONO_TYPE_BOOLEAN: {
8157 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8162 case MONO_TYPE_CHAR:
8164 case MONO_TYPE_I2: {
8165 guint16 *val = g_malloc (sizeof (guint16));
8170 #if SIZEOF_VOID_P == 4
8176 case MONO_TYPE_I4: {
8177 guint32 *val = g_malloc (sizeof (guint32));
8182 #if SIZEOF_VOID_P == 8
8183 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8187 case MONO_TYPE_I8: {
8188 guint64 *val = g_malloc (sizeof (guint64));
8193 case MONO_TYPE_R8: {
8194 double *val = g_malloc (sizeof (double));
8199 case MONO_TYPE_VALUETYPE:
8200 if (t->data.klass->enumtype) {
8201 type = mono_class_enum_basetype (t->data.klass)->type;
8204 MonoClass *k = t->data.klass;
8206 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8207 guint64 *val = g_malloc (sizeof (guint64));
8213 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8216 case MONO_TYPE_STRING:
8217 if (*p == (char)0xFF) {
8221 slen = mono_metadata_decode_value (p, &p);
8223 return mono_string_new_len (mono_domain_get (), p, slen);
8224 case MONO_TYPE_CLASS: {
8227 if (*p == (char)0xFF) {
8232 slen = mono_metadata_decode_value (p, &p);
8233 n = g_memdup (p, slen + 1);
8235 t = mono_reflection_type_from_name (n, image);
8237 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8238 /* We don't free n, it's consumed by mono_error */
8239 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8244 return mono_type_get_object (mono_domain_get (), t);
8246 case MONO_TYPE_OBJECT: {
8249 MonoClass *subc = NULL;
8254 } else if (subt == 0x0E) {
8255 type = MONO_TYPE_STRING;
8257 } else if (subt == 0x1D) {
8258 MonoType simple_type = {{0}};
8262 type = MONO_TYPE_SZARRAY;
8263 if (etype == 0x50) {
8264 tklass = mono_defaults.systemtype_class;
8265 } else if (etype == 0x55) {
8266 tklass = load_cattr_enum_type (image, p, &p, error);
8267 if (!mono_error_ok (error))
8271 /* See Partition II, Appendix B3 */
8272 etype = MONO_TYPE_OBJECT;
8273 simple_type.type = etype;
8274 tklass = mono_class_from_mono_type (&simple_type);
8277 } else if (subt == 0x55) {
8280 slen = mono_metadata_decode_value (p, &p);
8281 n = g_memdup (p, slen + 1);
8283 t = mono_reflection_type_from_name (n, image);
8285 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8286 /* We don't free n, it's consumed by mono_error */
8287 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8292 subc = mono_class_from_mono_type (t);
8293 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8294 MonoType simple_type = {{0}};
8295 simple_type.type = subt;
8296 subc = mono_class_from_mono_type (&simple_type);
8298 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8300 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8302 if (mono_error_ok (error)) {
8303 obj = mono_object_new (mono_domain_get (), subc);
8304 g_assert (!subc->has_references);
8305 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8311 case MONO_TYPE_SZARRAY: {
8313 guint32 i, alen, basetype;
8316 if (alen == 0xffffffff) {
8320 arr = mono_array_new (mono_domain_get(), tklass, alen);
8321 basetype = tklass->byval_arg.type;
8322 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8323 basetype = mono_class_enum_basetype (tklass)->type;
8328 case MONO_TYPE_BOOLEAN:
8329 for (i = 0; i < alen; i++) {
8330 MonoBoolean val = *p++;
8331 mono_array_set (arr, MonoBoolean, i, val);
8334 case MONO_TYPE_CHAR:
8337 for (i = 0; i < alen; i++) {
8338 guint16 val = read16 (p);
8339 mono_array_set (arr, guint16, i, val);
8346 for (i = 0; i < alen; i++) {
8347 guint32 val = read32 (p);
8348 mono_array_set (arr, guint32, i, val);
8353 for (i = 0; i < alen; i++) {
8356 mono_array_set (arr, double, i, val);
8362 for (i = 0; i < alen; i++) {
8363 guint64 val = read64 (p);
8364 mono_array_set (arr, guint64, i, val);
8368 case MONO_TYPE_CLASS:
8369 case MONO_TYPE_OBJECT:
8370 case MONO_TYPE_STRING:
8371 case MONO_TYPE_SZARRAY:
8372 for (i = 0; i < alen; i++) {
8373 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8374 if (!mono_error_ok (error))
8376 mono_array_setref (arr, i, item);
8380 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8386 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8392 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8394 static MonoClass *klass;
8395 static MonoMethod *ctor;
8397 void *params [2], *unboxed;
8400 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8402 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8404 params [0] = mono_type_get_object (mono_domain_get (), t);
8406 retval = mono_object_new (mono_domain_get (), klass);
8407 unboxed = mono_object_unbox (retval);
8408 mono_runtime_invoke (ctor, unboxed, params, NULL);
8414 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8416 static MonoClass *klass;
8417 static MonoMethod *ctor;
8419 void *unboxed, *params [2];
8422 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8424 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8427 params [1] = typedarg;
8428 retval = mono_object_new (mono_domain_get (), klass);
8429 unboxed = mono_object_unbox (retval);
8430 mono_runtime_invoke (ctor, unboxed, params, NULL);
8436 type_is_reference (MonoType *type)
8438 switch (type->type) {
8439 case MONO_TYPE_BOOLEAN:
8440 case MONO_TYPE_CHAR:
8453 case MONO_TYPE_VALUETYPE:
8461 free_param_data (MonoMethodSignature *sig, void **params) {
8463 for (i = 0; i < sig->param_count; ++i) {
8464 if (!type_is_reference (sig->params [i]))
8465 g_free (params [i]);
8470 * Find the field index in the metadata FieldDef table.
8473 find_field_index (MonoClass *klass, MonoClassField *field) {
8476 for (i = 0; i < klass->field.count; ++i) {
8477 if (field == &klass->fields [i])
8478 return klass->field.first + 1 + i;
8484 * Find the property index in the metadata Property table.
8487 find_property_index (MonoClass *klass, MonoProperty *property) {
8490 for (i = 0; i < klass->ext->property.count; ++i) {
8491 if (property == &klass->ext->properties [i])
8492 return klass->ext->property.first + 1 + i;
8498 * Find the event index in the metadata Event table.
8501 find_event_index (MonoClass *klass, MonoEvent *event) {
8504 for (i = 0; i < klass->ext->event.count; ++i) {
8505 if (event == &klass->ext->events [i])
8506 return klass->ext->event.first + 1 + i;
8512 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8514 const char *p = (const char*)data;
8516 guint32 i, j, num_named;
8518 void *params_buf [32];
8519 void **params = NULL;
8520 MonoMethodSignature *sig;
8521 MonoObject *exc = NULL;
8523 mono_error_init (error);
8525 mono_class_init (method->klass);
8527 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8528 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8533 attr = mono_object_new (mono_domain_get (), method->klass);
8534 mono_runtime_invoke (method, attr, NULL, NULL);
8538 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8541 /*g_print ("got attr %s\n", method->klass->name);*/
8543 sig = mono_method_signature (method);
8544 if (sig->param_count < 32) {
8545 params = params_buf;
8546 memset (params, 0, sizeof (void*) * sig->param_count);
8548 /* Allocate using GC so it gets GC tracking */
8549 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8554 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8555 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8556 if (!mono_error_ok (error))
8561 attr = mono_object_new (mono_domain_get (), method->klass);
8563 mono_runtime_invoke (method, attr, params, &exc);
8566 num_named = read16 (named);
8568 for (j = 0; j < num_named; j++) {
8570 char *name, named_type, data_type;
8571 named_type = *named++;
8572 data_type = *named++; /* type of data */
8573 if (data_type == MONO_TYPE_SZARRAY)
8574 data_type = *named++;
8575 if (data_type == MONO_TYPE_ENUM) {
8578 type_len = mono_metadata_decode_blob_size (named, &named);
8579 type_name = g_malloc (type_len + 1);
8580 memcpy (type_name, named, type_len);
8581 type_name [type_len] = 0;
8583 /* FIXME: lookup the type and check type consistency */
8586 name_len = mono_metadata_decode_blob_size (named, &named);
8587 name = g_malloc (name_len + 1);
8588 memcpy (name, named, name_len);
8589 name [name_len] = 0;
8591 if (named_type == 0x53) {
8592 MonoClassField *field;
8595 /* how this fail is a blackbox */
8596 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8598 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8603 val = load_cattr_value (image, field->type, named, &named, error);
8604 if (!mono_error_ok (error)) {
8606 if (!type_is_reference (field->type))
8611 mono_field_set_value (attr, field, val);
8612 if (!type_is_reference (field->type))
8614 } else if (named_type == 0x54) {
8617 MonoType *prop_type;
8619 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8622 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8628 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8633 /* can we have more that 1 arg in a custom attr named property? */
8634 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8635 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8637 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8638 if (!mono_error_ok (error)) {
8640 if (!type_is_reference (prop_type))
8641 g_free (pparams [0]);
8646 mono_property_set_value (prop, attr, pparams, NULL);
8647 if (!type_is_reference (prop_type))
8648 g_free (pparams [0]);
8653 free_param_data (method->signature, params);
8654 if (params != params_buf)
8655 mono_gc_free_fixed (params);
8660 free_param_data (method->signature, params);
8661 if (params != params_buf)
8662 mono_gc_free_fixed (params);
8664 mono_raise_exception ((MonoException*)exc);
8669 * mono_reflection_create_custom_attr_data_args:
8671 * Create an array of typed and named arguments from the cattr blob given by DATA.
8672 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8673 * NAMED_ARG_INFO will contain information about the named arguments.
8676 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)
8678 MonoArray *typedargs, *namedargs;
8679 MonoClass *attrklass;
8681 const char *p = (const char*)data;
8683 guint32 i, j, num_named;
8684 CattrNamedArg *arginfo = NULL;
8688 *named_arg_info = NULL;
8690 mono_error_init (error);
8692 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8693 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8697 mono_class_init (method->klass);
8699 domain = mono_domain_get ();
8701 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8704 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8708 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8712 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8713 if (!mono_error_ok (error)) {
8714 if (!type_is_reference (mono_method_signature (method)->params [i]))
8719 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8720 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8721 mono_array_setref (typedargs, i, obj);
8723 if (!type_is_reference (mono_method_signature (method)->params [i]))
8728 num_named = read16 (named);
8729 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8731 attrklass = method->klass;
8733 arginfo = g_new0 (CattrNamedArg, num_named);
8734 *named_arg_info = arginfo;
8736 for (j = 0; j < num_named; j++) {
8738 char *name, named_type, data_type;
8739 named_type = *named++;
8740 data_type = *named++; /* type of data */
8741 if (data_type == MONO_TYPE_SZARRAY)
8742 data_type = *named++;
8743 if (data_type == MONO_TYPE_ENUM) {
8746 type_len = mono_metadata_decode_blob_size (named, &named);
8747 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8750 type_name = g_malloc (type_len + 1);
8751 memcpy (type_name, named, type_len);
8752 type_name [type_len] = 0;
8754 /* FIXME: lookup the type and check type consistency */
8757 name_len = mono_metadata_decode_blob_size (named, &named);
8758 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8760 name = g_malloc (name_len + 1);
8761 memcpy (name, named, name_len);
8762 name [name_len] = 0;
8764 if (named_type == 0x53) {
8766 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8774 arginfo [j].type = field->type;
8775 arginfo [j].field = field;
8777 val = load_cattr_value (image, field->type, named, &named, error);
8778 if (!mono_error_ok (error)) {
8779 if (!type_is_reference (field->type))
8785 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8786 mono_array_setref (namedargs, j, obj);
8787 if (!type_is_reference (field->type))
8789 } else if (named_type == 0x54) {
8791 MonoType *prop_type;
8792 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8795 if (!prop || !prop->set) {
8800 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8801 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8803 arginfo [j].type = prop_type;
8804 arginfo [j].prop = prop;
8806 val = load_cattr_value (image, prop_type, named, &named, error);
8807 if (!mono_error_ok (error)) {
8808 if (!type_is_reference (prop_type))
8814 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8815 mono_array_setref (namedargs, j, obj);
8816 if (!type_is_reference (prop_type))
8822 *typed_args = typedargs;
8823 *named_args = namedargs;
8826 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8828 *named_arg_info = NULL;
8832 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8835 MonoArray *typedargs, *namedargs;
8838 CattrNamedArg *arginfo = NULL;
8848 image = assembly->assembly->image;
8849 method = ref_method->method;
8850 domain = mono_object_domain (ref_method);
8852 if (!mono_class_init (method->klass))
8853 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8855 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8856 if (!mono_error_ok (&error))
8857 mono_error_raise_exception (&error);
8858 if (mono_loader_get_last_error ())
8859 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8861 if (!typedargs || !namedargs) {
8866 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8867 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8868 MonoObject *typedarg;
8870 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8871 mono_array_setref (typedargs, i, typedarg);
8874 for (i = 0; i < mono_array_length (namedargs); ++i) {
8875 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8876 MonoObject *typedarg, *namedarg, *minfo;
8878 if (arginfo [i].prop)
8879 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8881 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8883 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8884 namedarg = create_cattr_named_arg (minfo, typedarg);
8886 mono_array_setref (namedargs, i, namedarg);
8889 *ctor_args = typedargs;
8890 *named_args = namedargs;
8895 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8897 static MonoMethod *ctor;
8902 g_assert (image->assembly);
8905 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8907 domain = mono_domain_get ();
8908 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8909 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8910 params [1] = mono_assembly_get_object (domain, image->assembly);
8911 params [2] = (gpointer)&cattr->data;
8912 params [3] = &cattr->data_size;
8913 mono_runtime_invoke (ctor, attr, params, NULL);
8918 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8924 mono_error_init (error);
8927 for (i = 0; i < cinfo->num_attrs; ++i) {
8928 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8932 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8934 for (i = 0; i < cinfo->num_attrs; ++i) {
8935 if (!cinfo->attrs [i].ctor)
8936 /* The cattr type is not finished yet */
8937 /* We should include the type name but cinfo doesn't contain it */
8938 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8939 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8940 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8941 if (!mono_error_ok (error))
8943 mono_array_setref (result, n, attr);
8951 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8954 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8955 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8961 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8967 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8968 for (i = 0; i < cinfo->num_attrs; ++i) {
8969 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8970 mono_array_setref (result, i, attr);
8976 * mono_custom_attrs_from_index:
8978 * Returns: NULL if no attributes are found or if a loading error occurs.
8981 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8983 guint32 mtoken, i, len;
8984 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8986 MonoCustomAttrInfo *ainfo;
8987 GList *tmp, *list = NULL;
8989 MonoCustomAttrEntry* attr;
8991 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8993 i = mono_metadata_custom_attrs_from_index (image, idx);
8997 while (i < ca->rows) {
8998 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9000 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9003 len = g_list_length (list);
9006 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9007 ainfo->num_attrs = len;
9008 ainfo->image = image;
9009 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9010 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9011 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9012 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9013 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9014 mtoken |= MONO_TOKEN_METHOD_DEF;
9016 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9017 mtoken |= MONO_TOKEN_MEMBER_REF;
9020 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9023 attr = &ainfo->attrs [i - 1];
9024 attr->ctor = mono_get_method (image, mtoken, NULL);
9026 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9032 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9033 /*FIXME raising an exception here doesn't make any sense*/
9034 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9039 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9040 attr->data_size = mono_metadata_decode_value (data, &data);
9041 attr->data = (guchar*)data;
9049 mono_custom_attrs_from_method (MonoMethod *method)
9054 * An instantiated method has the same cattrs as the generic method definition.
9056 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9057 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9059 if (method->is_inflated)
9060 method = ((MonoMethodInflated *) method)->declaring;
9062 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9063 return lookup_custom_attr (method->klass->image, method);
9066 /* Synthetic methods */
9069 idx = mono_method_get_index (method);
9070 idx <<= MONO_CUSTOM_ATTR_BITS;
9071 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9072 return mono_custom_attrs_from_index (method->klass->image, idx);
9076 mono_custom_attrs_from_class (MonoClass *klass)
9080 if (klass->generic_class)
9081 klass = klass->generic_class->container_class;
9083 if (image_is_dynamic (klass->image))
9084 return lookup_custom_attr (klass->image, klass);
9086 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9087 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9088 idx <<= MONO_CUSTOM_ATTR_BITS;
9089 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9091 idx = mono_metadata_token_index (klass->type_token);
9092 idx <<= MONO_CUSTOM_ATTR_BITS;
9093 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9095 return mono_custom_attrs_from_index (klass->image, idx);
9099 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9103 if (image_is_dynamic (assembly->image))
9104 return lookup_custom_attr (assembly->image, assembly);
9105 idx = 1; /* there is only one assembly */
9106 idx <<= MONO_CUSTOM_ATTR_BITS;
9107 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9108 return mono_custom_attrs_from_index (assembly->image, idx);
9111 static MonoCustomAttrInfo*
9112 mono_custom_attrs_from_module (MonoImage *image)
9116 if (image_is_dynamic (image))
9117 return lookup_custom_attr (image, image);
9118 idx = 1; /* there is only one module */
9119 idx <<= MONO_CUSTOM_ATTR_BITS;
9120 idx |= MONO_CUSTOM_ATTR_MODULE;
9121 return mono_custom_attrs_from_index (image, idx);
9125 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9129 if (image_is_dynamic (klass->image)) {
9130 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9131 return lookup_custom_attr (klass->image, property);
9133 idx = find_property_index (klass, property);
9134 idx <<= MONO_CUSTOM_ATTR_BITS;
9135 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9136 return mono_custom_attrs_from_index (klass->image, idx);
9140 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9144 if (image_is_dynamic (klass->image)) {
9145 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9146 return lookup_custom_attr (klass->image, event);
9148 idx = find_event_index (klass, event);
9149 idx <<= MONO_CUSTOM_ATTR_BITS;
9150 idx |= MONO_CUSTOM_ATTR_EVENT;
9151 return mono_custom_attrs_from_index (klass->image, idx);
9155 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9158 if (image_is_dynamic (klass->image)) {
9159 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9160 return lookup_custom_attr (klass->image, field);
9162 idx = find_field_index (klass, field);
9163 idx <<= MONO_CUSTOM_ATTR_BITS;
9164 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9165 return mono_custom_attrs_from_index (klass->image, idx);
9169 * mono_custom_attrs_from_param:
9170 * @method: handle to the method that we want to retrieve custom parameter information from
9171 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9173 * The result must be released with mono_custom_attrs_free().
9175 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9178 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9181 guint32 i, idx, method_index;
9182 guint32 param_list, param_last, param_pos, found;
9184 MonoReflectionMethodAux *aux;
9187 * An instantiated method has the same cattrs as the generic method definition.
9189 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9190 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9192 if (method->is_inflated)
9193 method = ((MonoMethodInflated *) method)->declaring;
9195 if (image_is_dynamic (method->klass->image)) {
9196 MonoCustomAttrInfo *res, *ainfo;
9199 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9200 if (!aux || !aux->param_cattr)
9203 /* Need to copy since it will be freed later */
9204 ainfo = aux->param_cattr [param];
9207 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9208 res = g_malloc0 (size);
9209 memcpy (res, ainfo, size);
9213 image = method->klass->image;
9214 method_index = mono_method_get_index (method);
9217 ca = &image->tables [MONO_TABLE_METHOD];
9219 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9220 if (method_index == ca->rows) {
9221 ca = &image->tables [MONO_TABLE_PARAM];
9222 param_last = ca->rows + 1;
9224 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9225 ca = &image->tables [MONO_TABLE_PARAM];
9228 for (i = param_list; i < param_last; ++i) {
9229 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9230 if (param_pos == param) {
9238 idx <<= MONO_CUSTOM_ATTR_BITS;
9239 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9240 return mono_custom_attrs_from_index (image, idx);
9244 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9248 for (i = 0; i < ainfo->num_attrs; ++i) {
9249 klass = ainfo->attrs [i].ctor->klass;
9250 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9257 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9260 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9261 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9266 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9272 mono_error_init (error);
9275 for (i = 0; i < ainfo->num_attrs; ++i) {
9276 klass = ainfo->attrs [i].ctor->klass;
9277 if (mono_class_has_parent (klass, attr_klass)) {
9282 if (attr_index == -1)
9285 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9286 if (!mono_error_ok (error))
9288 return mono_array_get (attrs, MonoObject*, attr_index);
9292 * mono_reflection_get_custom_attrs_info:
9293 * @obj: a reflection object handle
9295 * Return the custom attribute info for attributes defined for the
9296 * reflection handle @obj. The objects.
9298 * FIXME this function leaks like a sieve for SRE objects.
9301 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9304 MonoCustomAttrInfo *cinfo = NULL;
9306 klass = obj->vtable->klass;
9307 if (klass == mono_defaults.monotype_class) {
9308 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9309 klass = mono_class_from_mono_type (type);
9310 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9311 cinfo = mono_custom_attrs_from_class (klass);
9312 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9313 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9314 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9315 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9316 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9317 cinfo = mono_custom_attrs_from_module (module->image);
9318 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9319 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9320 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9321 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9322 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9323 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9324 } else if (strcmp ("MonoField", klass->name) == 0) {
9325 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9326 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9327 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9328 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9329 cinfo = mono_custom_attrs_from_method (rmethod->method);
9330 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9331 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9332 cinfo = mono_custom_attrs_from_method (rmethod->method);
9333 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9334 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9335 MonoClass *member_class = mono_object_class (param->MemberImpl);
9336 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9337 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9338 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9339 } else if (is_sr_mono_property (member_class)) {
9340 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9342 if (!(method = prop->property->get))
9343 method = prop->property->set;
9346 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9348 #ifndef DISABLE_REFLECTION_EMIT
9349 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9350 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9351 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9352 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9353 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9354 MonoMethod *method = NULL;
9355 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9356 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9357 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9358 method = ((MonoReflectionMethod *)c->cb)->method;
9360 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));
9362 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9366 char *type_name = mono_type_get_full_name (member_class);
9367 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9368 MonoException *ex = mono_get_exception_not_supported (msg);
9371 mono_raise_exception (ex);
9373 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9374 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9375 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9376 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9377 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9378 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9379 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9380 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9381 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9382 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9383 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9384 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9385 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9386 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9387 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9388 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9389 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9390 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9391 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9392 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9393 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9394 } else { /* handle other types here... */
9395 g_error ("get custom attrs not yet supported for %s", klass->name);
9402 * mono_reflection_get_custom_attrs_by_type:
9403 * @obj: a reflection object handle
9405 * Return an array with all the custom attributes defined of the
9406 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9407 * of that type are returned. The objects are fully build. Return NULL if a loading error
9411 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9414 MonoCustomAttrInfo *cinfo;
9416 mono_error_init (error);
9418 cinfo = mono_reflection_get_custom_attrs_info (obj);
9420 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9422 mono_custom_attrs_free (cinfo);
9424 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9425 if (mono_loader_get_last_error ())
9427 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9434 * mono_reflection_get_custom_attrs:
9435 * @obj: a reflection object handle
9437 * Return an array with all the custom attributes defined of the
9438 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9442 mono_reflection_get_custom_attrs (MonoObject *obj)
9446 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9450 * mono_reflection_get_custom_attrs_data:
9451 * @obj: a reflection obj handle
9453 * Returns an array of System.Reflection.CustomAttributeData,
9454 * which include information about attributes reflected on
9455 * types loaded using the Reflection Only methods
9458 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9461 MonoCustomAttrInfo *cinfo;
9463 cinfo = mono_reflection_get_custom_attrs_info (obj);
9465 result = mono_custom_attrs_data_construct (cinfo);
9467 mono_custom_attrs_free (cinfo);
9469 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9474 static MonoReflectionType*
9475 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9477 static MonoMethod *method_get_underlying_system_type = NULL;
9478 MonoMethod *usertype_method;
9480 if (!method_get_underlying_system_type)
9481 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9482 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9483 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9488 is_corlib_type (MonoClass *klass)
9490 return klass->image == mono_defaults.corlib;
9493 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9494 static MonoClass *cached_class; \
9496 return cached_class == _class; \
9497 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9498 cached_class = _class; \
9505 #ifndef DISABLE_REFLECTION_EMIT
9507 is_sre_array (MonoClass *klass)
9509 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9513 is_sre_byref (MonoClass *klass)
9515 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9519 is_sre_pointer (MonoClass *klass)
9521 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9525 is_sre_generic_instance (MonoClass *klass)
9527 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9531 is_sre_type_builder (MonoClass *klass)
9533 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9537 is_sre_method_builder (MonoClass *klass)
9539 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9543 is_sre_ctor_builder (MonoClass *klass)
9545 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9549 is_sre_field_builder (MonoClass *klass)
9551 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9555 is_sre_method_on_tb_inst (MonoClass *klass)
9557 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9561 is_sre_ctor_on_tb_inst (MonoClass *klass)
9563 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9567 mono_reflection_type_get_handle (MonoReflectionType* ref)
9575 if (is_usertype (ref)) {
9576 ref = mono_reflection_type_get_underlying_system_type (ref);
9577 if (ref == NULL || is_usertype (ref))
9583 klass = mono_object_class (ref);
9585 if (is_sre_array (klass)) {
9587 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9588 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9590 if (sre_array->rank == 0) //single dimentional array
9591 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9593 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9594 sre_array->type.type = res;
9596 } else if (is_sre_byref (klass)) {
9598 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9599 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9601 res = &mono_class_from_mono_type (base)->this_arg;
9602 sre_byref->type.type = res;
9604 } else if (is_sre_pointer (klass)) {
9606 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9607 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9609 res = &mono_ptr_class_get (base)->byval_arg;
9610 sre_pointer->type.type = res;
9612 } else if (is_sre_generic_instance (klass)) {
9613 MonoType *res, **types;
9614 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9617 count = mono_array_length (gclass->type_arguments);
9618 types = g_new0 (MonoType*, count);
9619 for (i = 0; i < count; ++i) {
9620 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9621 types [i] = mono_reflection_type_get_handle (t);
9628 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9631 gclass->type.type = res;
9635 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9642 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9644 mono_reflection_type_get_handle (type);
9648 mono_reflection_register_with_runtime (MonoReflectionType *type)
9650 MonoType *res = mono_reflection_type_get_handle (type);
9651 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9655 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9657 klass = mono_class_from_mono_type (res);
9659 mono_loader_lock (); /*same locking as mono_type_get_object*/
9660 mono_domain_lock (domain);
9662 if (!image_is_dynamic (klass->image)) {
9663 mono_class_setup_supertypes (klass);
9665 if (!domain->type_hash)
9666 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9667 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9668 mono_g_hash_table_insert (domain->type_hash, res, type);
9670 mono_domain_unlock (domain);
9671 mono_loader_unlock ();
9675 * LOCKING: Assumes the loader lock is held.
9677 static MonoMethodSignature*
9678 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9679 MonoMethodSignature *sig;
9682 count = parameters? mono_array_length (parameters): 0;
9684 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9685 sig->param_count = count;
9686 sig->sentinelpos = -1; /* FIXME */
9687 for (i = 0; i < count; ++i)
9688 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9693 * LOCKING: Assumes the loader lock is held.
9695 static MonoMethodSignature*
9696 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9697 MonoMethodSignature *sig;
9699 sig = parameters_to_signature (image, ctor->parameters);
9700 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9701 sig->ret = &mono_defaults.void_class->byval_arg;
9706 * LOCKING: Assumes the loader lock is held.
9708 static MonoMethodSignature*
9709 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9710 MonoMethodSignature *sig;
9712 sig = parameters_to_signature (image, method->parameters);
9713 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9714 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9715 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9719 static MonoMethodSignature*
9720 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9721 MonoMethodSignature *sig;
9723 sig = parameters_to_signature (NULL, method->parameters);
9724 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9725 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9726 sig->generic_param_count = 0;
9731 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9733 MonoClass *klass = mono_object_class (prop);
9734 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9735 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9736 *name = mono_string_to_utf8 (pb->name);
9737 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9739 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9740 *name = g_strdup (p->property->name);
9741 if (p->property->get)
9742 *type = mono_method_signature (p->property->get)->ret;
9744 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9749 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9751 MonoClass *klass = mono_object_class (field);
9752 if (strcmp (klass->name, "FieldBuilder") == 0) {
9753 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9754 *name = mono_string_to_utf8 (fb->name);
9755 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9757 MonoReflectionField *f = (MonoReflectionField *)field;
9758 *name = g_strdup (mono_field_get_name (f->field));
9759 *type = f->field->type;
9763 #else /* DISABLE_REFLECTION_EMIT */
9766 mono_reflection_register_with_runtime (MonoReflectionType *type)
9772 is_sre_type_builder (MonoClass *klass)
9778 is_sre_generic_instance (MonoClass *klass)
9784 init_type_builder_generics (MonoObject *type)
9788 #endif /* !DISABLE_REFLECTION_EMIT */
9792 is_sr_mono_field (MonoClass *klass)
9794 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9798 is_sr_mono_property (MonoClass *klass)
9800 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9804 is_sr_mono_method (MonoClass *klass)
9806 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9810 is_sr_mono_cmethod (MonoClass *klass)
9812 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9816 is_sr_mono_generic_method (MonoClass *klass)
9818 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9822 is_sr_mono_generic_cmethod (MonoClass *klass)
9824 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9828 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9830 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9834 is_usertype (MonoReflectionType *ref)
9836 MonoClass *klass = mono_object_class (ref);
9837 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9840 static MonoReflectionType*
9841 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9843 if (!type || type->type)
9846 if (is_usertype (type)) {
9847 type = mono_reflection_type_get_underlying_system_type (type);
9848 if (is_usertype (type))
9849 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9855 * Encode a value in a custom attribute stream of bytes.
9856 * The value to encode is either supplied as an object in argument val
9857 * (valuetypes are boxed), or as a pointer to the data in the
9859 * @type represents the type of the value
9860 * @buffer is the start of the buffer
9861 * @p the current position in the buffer
9862 * @buflen contains the size of the buffer and is used to return the new buffer size
9863 * if this needs to be realloced.
9864 * @retbuffer and @retp return the start and the position of the buffer
9867 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9869 MonoTypeEnum simple_type;
9871 if ((p-buffer) + 10 >= *buflen) {
9874 newbuf = g_realloc (buffer, *buflen);
9875 p = newbuf + (p-buffer);
9879 argval = ((char*)arg + sizeof (MonoObject));
9880 simple_type = type->type;
9882 switch (simple_type) {
9883 case MONO_TYPE_BOOLEAN:
9888 case MONO_TYPE_CHAR:
9891 swap_with_size (p, argval, 2, 1);
9897 swap_with_size (p, argval, 4, 1);
9901 swap_with_size (p, argval, 8, 1);
9906 swap_with_size (p, argval, 8, 1);
9909 case MONO_TYPE_VALUETYPE:
9910 if (type->data.klass->enumtype) {
9911 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9914 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9917 case MONO_TYPE_STRING: {
9924 str = mono_string_to_utf8 ((MonoString*)arg);
9925 slen = strlen (str);
9926 if ((p-buffer) + 10 + slen >= *buflen) {
9930 newbuf = g_realloc (buffer, *buflen);
9931 p = newbuf + (p-buffer);
9934 mono_metadata_encode_value (slen, p, &p);
9935 memcpy (p, str, slen);
9940 case MONO_TYPE_CLASS: {
9948 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9949 slen = strlen (str);
9950 if ((p-buffer) + 10 + slen >= *buflen) {
9954 newbuf = g_realloc (buffer, *buflen);
9955 p = newbuf + (p-buffer);
9958 mono_metadata_encode_value (slen, p, &p);
9959 memcpy (p, str, slen);
9964 case MONO_TYPE_SZARRAY: {
9966 MonoClass *eclass, *arg_eclass;
9969 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9972 len = mono_array_length ((MonoArray*)arg);
9974 *p++ = (len >> 8) & 0xff;
9975 *p++ = (len >> 16) & 0xff;
9976 *p++ = (len >> 24) & 0xff;
9978 *retbuffer = buffer;
9979 eclass = type->data.klass;
9980 arg_eclass = mono_object_class (arg)->element_class;
9983 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9984 eclass = mono_defaults.object_class;
9986 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9987 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9988 int elsize = mono_class_array_element_size (arg_eclass);
9989 for (i = 0; i < len; ++i) {
9990 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9993 } else if (eclass->valuetype && arg_eclass->valuetype) {
9994 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9995 int elsize = mono_class_array_element_size (eclass);
9996 for (i = 0; i < len; ++i) {
9997 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10001 for (i = 0; i < len; ++i) {
10002 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10007 case MONO_TYPE_OBJECT: {
10013 * The parameter type is 'object' but the type of the actual
10014 * argument is not. So we have to add type information to the blob
10015 * too. This is completely undocumented in the spec.
10019 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10024 klass = mono_object_class (arg);
10026 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10029 } else if (klass->enumtype) {
10031 } else if (klass == mono_defaults.string_class) {
10032 simple_type = MONO_TYPE_STRING;
10035 } else if (klass->rank == 1) {
10037 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10038 /* See Partition II, Appendix B3 */
10041 *p++ = klass->element_class->byval_arg.type;
10042 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10044 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10045 *p++ = simple_type = klass->byval_arg.type;
10048 g_error ("unhandled type in custom attr");
10050 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10051 slen = strlen (str);
10052 if ((p-buffer) + 10 + slen >= *buflen) {
10056 newbuf = g_realloc (buffer, *buflen);
10057 p = newbuf + (p-buffer);
10060 mono_metadata_encode_value (slen, p, &p);
10061 memcpy (p, str, slen);
10064 simple_type = mono_class_enum_basetype (klass)->type;
10068 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10071 *retbuffer = buffer;
10075 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10077 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10078 char *str = type_get_qualified_name (type, NULL);
10079 int slen = strlen (str);
10083 * This seems to be optional...
10086 mono_metadata_encode_value (slen, p, &p);
10087 memcpy (p, str, slen);
10090 } else if (type->type == MONO_TYPE_OBJECT) {
10092 } else if (type->type == MONO_TYPE_CLASS) {
10093 /* it should be a type: encode_cattr_value () has the check */
10096 mono_metadata_encode_value (type->type, p, &p);
10097 if (type->type == MONO_TYPE_SZARRAY)
10098 /* See the examples in Partition VI, Annex B */
10099 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10105 #ifndef DISABLE_REFLECTION_EMIT
10107 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10110 /* Preallocate a large enough buffer */
10111 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10112 char *str = type_get_qualified_name (type, NULL);
10113 len = strlen (str);
10115 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10116 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10117 len = strlen (str);
10122 len += strlen (name);
10124 if ((p-buffer) + 20 + len >= *buflen) {
10128 newbuf = g_realloc (buffer, *buflen);
10129 p = newbuf + (p-buffer);
10133 encode_field_or_prop_type (type, p, &p);
10135 len = strlen (name);
10136 mono_metadata_encode_value (len, p, &p);
10137 memcpy (p, name, len);
10139 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10141 *retbuffer = buffer;
10145 * mono_reflection_get_custom_attrs_blob:
10146 * @ctor: custom attribute constructor
10147 * @ctorArgs: arguments o the constructor
10153 * Creates the blob of data that needs to be saved in the metadata and that represents
10154 * the custom attributed described by @ctor, @ctorArgs etc.
10155 * Returns: a Byte array representing the blob of data.
10158 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10161 MonoMethodSignature *sig;
10166 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10167 /* sig is freed later so allocate it in the heap */
10168 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10170 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10173 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10175 p = buffer = g_malloc (buflen);
10176 /* write the prolog */
10179 for (i = 0; i < sig->param_count; ++i) {
10180 arg = mono_array_get (ctorArgs, MonoObject*, i);
10181 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10185 i += mono_array_length (properties);
10187 i += mono_array_length (fields);
10189 *p++ = (i >> 8) & 0xff;
10192 for (i = 0; i < mono_array_length (properties); ++i) {
10196 prop = mono_array_get (properties, gpointer, i);
10197 get_prop_name_and_type (prop, &pname, &ptype);
10198 *p++ = 0x54; /* PROPERTY signature */
10199 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10206 for (i = 0; i < mono_array_length (fields); ++i) {
10210 field = mono_array_get (fields, gpointer, i);
10211 get_field_name_and_type (field, &fname, &ftype);
10212 *p++ = 0x53; /* FIELD signature */
10213 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10218 g_assert (p - buffer <= buflen);
10219 buflen = p - buffer;
10220 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10221 p = mono_array_addr (result, char, 0);
10222 memcpy (p, buffer, buflen);
10224 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10230 * mono_reflection_setup_internal_class:
10231 * @tb: a TypeBuilder object
10233 * Creates a MonoClass that represents the TypeBuilder.
10234 * This is a trick that lets us simplify a lot of reflection code
10235 * (and will allow us to support Build and Run assemblies easier).
10238 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10241 MonoClass *klass, *parent;
10243 RESOLVE_TYPE (tb->parent);
10245 mono_loader_lock ();
10248 /* check so we can compile corlib correctly */
10249 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10250 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10251 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10253 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10259 /* the type has already being created: it means we just have to change the parent */
10260 if (tb->type.type) {
10261 klass = mono_class_from_mono_type (tb->type.type);
10262 klass->parent = NULL;
10263 /* fool mono_class_setup_parent */
10264 klass->supertypes = NULL;
10265 mono_class_setup_parent (klass, parent);
10266 mono_class_setup_mono_type (klass);
10267 mono_loader_unlock ();
10271 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10273 klass->image = &tb->module->dynamic_image->image;
10275 klass->inited = 1; /* we lie to the runtime */
10276 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10277 if (!mono_error_ok (&error))
10279 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10280 if (!mono_error_ok (&error))
10282 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10283 klass->flags = tb->attrs;
10285 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10287 klass->element_class = klass;
10289 if (mono_class_get_ref_info (klass) == NULL) {
10291 mono_class_set_ref_info (klass, tb);
10293 /* Put into cache so mono_class_get_checked () will find it.
10294 Skip nested types as those should not be available on the global scope. */
10295 if (!tb->nesting_type)
10296 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10299 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10300 by performing a mono_class_get which does the full resolution.
10302 Working around this semantics would require us to write a lot of code for no clear advantage.
10304 mono_image_append_class_to_reflection_info_set (klass);
10306 g_assert (mono_class_get_ref_info (klass) == tb);
10309 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10311 if (parent != NULL) {
10312 mono_class_setup_parent (klass, parent);
10313 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10314 const char *old_n = klass->name;
10315 /* trick to get relative numbering right when compiling corlib */
10316 klass->name = "BuildingObject";
10317 mono_class_setup_parent (klass, mono_defaults.object_class);
10318 klass->name = old_n;
10321 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10322 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10323 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10324 klass->instance_size = sizeof (MonoObject);
10325 klass->size_inited = 1;
10326 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10329 mono_class_setup_mono_type (klass);
10331 mono_class_setup_supertypes (klass);
10334 * FIXME: handle interfaces.
10337 tb->type.type = &klass->byval_arg;
10339 if (tb->nesting_type) {
10340 g_assert (tb->nesting_type->type);
10341 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10344 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10346 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10348 mono_loader_unlock ();
10352 mono_loader_unlock ();
10353 mono_error_raise_exception (&error);
10357 * mono_reflection_setup_generic_class:
10358 * @tb: a TypeBuilder object
10360 * Setup the generic class before adding the first generic parameter.
10363 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10368 * mono_reflection_create_generic_class:
10369 * @tb: a TypeBuilder object
10371 * Creates the generic class after all generic parameters have been added.
10374 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10379 klass = mono_class_from_mono_type (tb->type.type);
10381 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10383 if (klass->generic_container || (count == 0))
10386 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10388 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10390 klass->generic_container->owner.klass = klass;
10391 klass->generic_container->type_argc = count;
10392 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10394 klass->is_generic = 1;
10396 for (i = 0; i < count; i++) {
10397 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10398 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10399 klass->generic_container->type_params [i] = *param;
10400 /*Make sure we are a diferent type instance */
10401 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10402 klass->generic_container->type_params [i].info.pklass = NULL;
10403 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10405 g_assert (klass->generic_container->type_params [i].param.owner);
10408 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10412 * mono_reflection_create_internal_class:
10413 * @tb: a TypeBuilder object
10415 * Actually create the MonoClass that is associated with the TypeBuilder.
10418 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10422 klass = mono_class_from_mono_type (tb->type.type);
10424 mono_loader_lock ();
10425 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10426 MonoReflectionFieldBuilder *fb;
10428 MonoType *enum_basetype;
10430 g_assert (tb->fields != NULL);
10431 g_assert (mono_array_length (tb->fields) >= 1);
10433 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10435 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10436 mono_loader_unlock ();
10440 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10441 klass->element_class = mono_class_from_mono_type (enum_basetype);
10442 if (!klass->element_class)
10443 klass->element_class = mono_class_from_mono_type (enum_basetype);
10446 * get the element_class from the current corlib.
10448 ec = default_class_from_mono_type (enum_basetype);
10449 klass->instance_size = ec->instance_size;
10450 klass->size_inited = 1;
10452 * this is almost safe to do with enums and it's needed to be able
10453 * to create objects of the enum type (for use in SetConstant).
10455 /* FIXME: Does this mean enums can't have method overrides ? */
10456 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10458 mono_loader_unlock ();
10461 static MonoMarshalSpec*
10462 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10463 MonoReflectionMarshal *minfo)
10465 MonoMarshalSpec *res;
10467 res = image_g_new0 (image, MonoMarshalSpec, 1);
10468 res->native = minfo->type;
10470 switch (minfo->type) {
10471 case MONO_NATIVE_LPARRAY:
10472 res->data.array_data.elem_type = minfo->eltype;
10473 if (minfo->has_size) {
10474 res->data.array_data.param_num = minfo->param_num;
10475 res->data.array_data.num_elem = minfo->count;
10476 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10479 res->data.array_data.param_num = -1;
10480 res->data.array_data.num_elem = -1;
10481 res->data.array_data.elem_mult = -1;
10485 case MONO_NATIVE_BYVALTSTR:
10486 case MONO_NATIVE_BYVALARRAY:
10487 res->data.array_data.num_elem = minfo->count;
10490 case MONO_NATIVE_CUSTOM:
10491 if (minfo->marshaltyperef)
10492 res->data.custom_data.custom_name =
10493 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10494 if (minfo->mcookie)
10495 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10504 #endif /* !DISABLE_REFLECTION_EMIT */
10506 MonoReflectionMarshalAsAttribute*
10507 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10508 MonoMarshalSpec *spec)
10510 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10511 MonoReflectionMarshalAsAttribute *minfo;
10514 if (!System_Reflection_Emit_MarshalAsAttribute) {
10515 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10516 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10517 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10520 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10521 minfo->utype = spec->native;
10523 switch (minfo->utype) {
10524 case MONO_NATIVE_LPARRAY:
10525 minfo->array_subtype = spec->data.array_data.elem_type;
10526 minfo->size_const = spec->data.array_data.num_elem;
10527 if (spec->data.array_data.param_num != -1)
10528 minfo->size_param_index = spec->data.array_data.param_num;
10531 case MONO_NATIVE_BYVALTSTR:
10532 case MONO_NATIVE_BYVALARRAY:
10533 minfo->size_const = spec->data.array_data.num_elem;
10536 case MONO_NATIVE_CUSTOM:
10537 if (spec->data.custom_data.custom_name) {
10538 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10540 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10542 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10544 if (spec->data.custom_data.cookie)
10545 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10555 #ifndef DISABLE_REFLECTION_EMIT
10557 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10558 ReflectionMethodBuilder *rmb,
10559 MonoMethodSignature *sig)
10563 MonoMethodWrapper *wrapperm;
10564 MonoMarshalSpec **specs;
10565 MonoReflectionMethodAux *method_aux;
10570 mono_error_init (&error);
10572 * Methods created using a MethodBuilder should have their memory allocated
10573 * inside the image mempool, while dynamic methods should have their memory
10576 dynamic = rmb->refs != NULL;
10577 image = dynamic ? NULL : klass->image;
10580 g_assert (!klass->generic_class);
10582 mono_loader_lock ();
10584 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10585 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10586 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10588 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10590 wrapperm = (MonoMethodWrapper*)m;
10592 m->dynamic = dynamic;
10594 m->flags = rmb->attrs;
10595 m->iflags = rmb->iattrs;
10596 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10598 m->signature = sig;
10599 m->sre_method = TRUE;
10600 m->skip_visibility = rmb->skip_visibility;
10601 if (rmb->table_idx)
10602 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10604 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10605 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10606 m->string_ctor = 1;
10608 m->signature->pinvoke = 1;
10609 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10610 m->signature->pinvoke = 1;
10612 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10614 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10615 g_assert (mono_error_ok (&error));
10616 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10617 g_assert (mono_error_ok (&error));
10619 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10621 if (image_is_dynamic (klass->image))
10622 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10624 mono_loader_unlock ();
10627 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10628 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10629 MonoMethodHeader *header;
10631 gint32 max_stack, i;
10632 gint32 num_locals = 0;
10633 gint32 num_clauses = 0;
10637 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10638 code_size = rmb->ilgen->code_len;
10639 max_stack = rmb->ilgen->max_stack;
10640 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10641 if (rmb->ilgen->ex_handlers)
10642 num_clauses = method_count_clauses (rmb->ilgen);
10645 code = mono_array_addr (rmb->code, guint8, 0);
10646 code_size = mono_array_length (rmb->code);
10647 /* we probably need to run a verifier on the code... */
10657 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10658 header->code_size = code_size;
10659 header->code = image_g_malloc (image, code_size);
10660 memcpy ((char*)header->code, code, code_size);
10661 header->max_stack = max_stack;
10662 header->init_locals = rmb->init_locals;
10663 header->num_locals = num_locals;
10665 for (i = 0; i < num_locals; ++i) {
10666 MonoReflectionLocalBuilder *lb =
10667 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10669 header->locals [i] = image_g_new0 (image, MonoType, 1);
10670 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10673 header->num_clauses = num_clauses;
10675 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10676 rmb->ilgen, num_clauses);
10679 wrapperm->header = header;
10682 if (rmb->generic_params) {
10683 int count = mono_array_length (rmb->generic_params);
10684 MonoGenericContainer *container = rmb->generic_container;
10686 g_assert (container);
10688 container->type_argc = count;
10689 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10690 container->owner.method = m;
10692 m->is_generic = TRUE;
10693 mono_method_set_generic_container (m, container);
10695 for (i = 0; i < count; i++) {
10696 MonoReflectionGenericParam *gp =
10697 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10698 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10699 container->type_params [i] = *param;
10703 * The method signature might have pointers to generic parameters that belong to other methods.
10704 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10705 * generic parameters.
10707 for (i = 0; i < m->signature->param_count; ++i) {
10708 MonoType *t = m->signature->params [i];
10709 if (t->type == MONO_TYPE_MVAR) {
10710 MonoGenericParam *gparam = t->data.generic_param;
10711 if (gparam->num < count) {
10712 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10713 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10719 if (klass->generic_container) {
10720 container->parent = klass->generic_container;
10721 container->context.class_inst = klass->generic_container->context.class_inst;
10723 container->context.method_inst = mono_get_shared_generic_inst (container);
10727 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10731 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10733 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10734 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10735 for (i = 0; i < rmb->nrefs; ++i)
10736 data [i + 1] = rmb->refs [i];
10741 /* Parameter info */
10744 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10745 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10746 for (i = 0; i <= m->signature->param_count; ++i) {
10747 MonoReflectionParamBuilder *pb;
10748 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10749 if ((i > 0) && (pb->attrs)) {
10750 /* Make a copy since it might point to a shared type structure */
10751 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10752 m->signature->params [i - 1]->attrs = pb->attrs;
10755 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10756 MonoDynamicImage *assembly;
10757 guint32 idx, def_type, len;
10761 if (!method_aux->param_defaults) {
10762 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10763 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10765 assembly = (MonoDynamicImage*)klass->image;
10766 idx = encode_constant (assembly, pb->def_value, &def_type);
10767 /* Copy the data from the blob since it might get realloc-ed */
10768 p = assembly->blob.data + idx;
10769 len = mono_metadata_decode_blob_size (p, &p2);
10771 method_aux->param_defaults [i] = image_g_malloc (image, len);
10772 method_aux->param_default_types [i] = def_type;
10773 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10777 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10778 g_assert (mono_error_ok (&error));
10781 if (!method_aux->param_cattr)
10782 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10783 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10789 /* Parameter marshalling */
10792 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10793 MonoReflectionParamBuilder *pb;
10794 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10795 if (pb->marshal_info) {
10797 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10798 specs [pb->position] =
10799 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10803 if (specs != NULL) {
10805 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10806 method_aux->param_marshall = specs;
10809 if (image_is_dynamic (klass->image) && method_aux)
10810 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10812 mono_loader_unlock ();
10818 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10820 ReflectionMethodBuilder rmb;
10821 MonoMethodSignature *sig;
10823 mono_loader_lock ();
10824 sig = ctor_builder_to_signature (klass->image, mb);
10825 mono_loader_unlock ();
10827 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10829 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10830 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10832 /* If we are in a generic class, we might be called multiple times from inflate_method */
10833 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10834 /* ilgen is no longer needed */
10838 return mb->mhandle;
10842 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10844 ReflectionMethodBuilder rmb;
10845 MonoMethodSignature *sig;
10847 mono_loader_lock ();
10848 sig = method_builder_to_signature (klass->image, mb);
10849 mono_loader_unlock ();
10851 reflection_methodbuilder_from_method_builder (&rmb, mb);
10853 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10854 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10856 /* If we are in a generic class, we might be called multiple times from inflate_method */
10857 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10858 /* ilgen is no longer needed */
10861 return mb->mhandle;
10864 static MonoClassField*
10865 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10867 MonoClassField *field;
10871 field = g_new0 (MonoClassField, 1);
10873 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10874 g_assert (mono_error_ok (&error));
10875 if (fb->attrs || fb->modreq || fb->modopt) {
10876 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10877 field->type->attrs = fb->attrs;
10879 g_assert (image_is_dynamic (klass->image));
10880 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10881 g_free (field->type);
10882 field->type = mono_metadata_type_dup (klass->image, custom);
10885 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10887 if (fb->offset != -1)
10888 field->offset = fb->offset;
10889 field->parent = klass;
10890 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10892 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10899 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10902 MonoReflectionTypeBuilder *tb = NULL;
10903 gboolean is_dynamic = FALSE;
10904 MonoClass *geninst;
10906 mono_loader_lock ();
10908 if (is_sre_type_builder (mono_object_class (type))) {
10909 tb = (MonoReflectionTypeBuilder *) type;
10912 } else if (is_sre_generic_instance (mono_object_class (type))) {
10913 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10914 MonoReflectionType *gtd = rgi->generic_type;
10916 if (is_sre_type_builder (mono_object_class (gtd))) {
10917 tb = (MonoReflectionTypeBuilder *)gtd;
10922 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10923 if (tb && tb->generic_container)
10924 mono_reflection_create_generic_class (tb);
10926 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10927 if (!klass->generic_container) {
10928 mono_loader_unlock ();
10932 if (klass->wastypebuilder) {
10933 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10938 mono_loader_unlock ();
10940 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10942 return &geninst->byval_arg;
10946 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10948 MonoGenericClass *gclass;
10949 MonoGenericInst *inst;
10951 g_assert (klass->generic_container);
10953 inst = mono_metadata_get_generic_inst (type_argc, types);
10954 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10956 return mono_generic_class_get_class (gclass);
10959 MonoReflectionMethod*
10960 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10964 MonoMethod *method, *inflated;
10965 MonoMethodInflated *imethod;
10966 MonoGenericContext tmp_context;
10967 MonoGenericInst *ginst;
10968 MonoType **type_argv;
10971 /*FIXME but this no longer should happen*/
10972 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10973 #ifndef DISABLE_REFLECTION_EMIT
10974 MonoReflectionMethodBuilder *mb = NULL;
10975 MonoReflectionTypeBuilder *tb;
10978 mb = (MonoReflectionMethodBuilder *) rmethod;
10979 tb = (MonoReflectionTypeBuilder *) mb->type;
10980 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10982 method = methodbuilder_to_mono_method (klass, mb);
10984 g_assert_not_reached ();
10988 method = rmethod->method;
10991 klass = method->klass;
10993 if (method->is_inflated)
10994 method = ((MonoMethodInflated *) method)->declaring;
10996 count = mono_method_signature (method)->generic_param_count;
10997 if (count != mono_array_length (types))
11000 type_argv = g_new0 (MonoType *, count);
11001 for (i = 0; i < count; i++) {
11002 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
11003 type_argv [i] = mono_reflection_type_get_handle (garg);
11005 ginst = mono_metadata_get_generic_inst (count, type_argv);
11006 g_free (type_argv);
11008 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11009 tmp_context.method_inst = ginst;
11011 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11012 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11013 imethod = (MonoMethodInflated *) inflated;
11015 /*FIXME but I think this is no longer necessary*/
11016 if (image_is_dynamic (method->klass->image)) {
11017 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11019 * This table maps metadata structures representing inflated methods/fields
11020 * to the reflection objects representing their generic definitions.
11022 mono_image_lock ((MonoImage*)image);
11023 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11024 mono_image_unlock ((MonoImage*)image);
11027 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11028 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11030 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11033 #ifndef DISABLE_REFLECTION_EMIT
11035 static MonoMethod *
11036 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11038 MonoMethodInflated *imethod;
11039 MonoGenericContext *context;
11043 * With generic code sharing the klass might not be inflated.
11044 * This can happen because classes inflated with their own
11045 * type arguments are "normalized" to the uninflated class.
11047 if (!klass->generic_class)
11050 context = mono_class_get_context (klass);
11052 if (klass->method.count && klass->methods) {
11053 /* Find the already created inflated method */
11054 for (i = 0; i < klass->method.count; ++i) {
11055 g_assert (klass->methods [i]->is_inflated);
11056 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11059 g_assert (i < klass->method.count);
11060 imethod = (MonoMethodInflated*)klass->methods [i];
11063 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11064 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11067 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11068 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11070 mono_image_lock ((MonoImage*)image);
11071 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11072 mono_image_unlock ((MonoImage*)image);
11074 return (MonoMethod *) imethod;
11077 static MonoMethod *
11078 inflate_method (MonoReflectionType *type, MonoObject *obj)
11080 MonoMethod *method;
11083 MonoClass *type_class = mono_object_class (type);
11085 if (is_sre_generic_instance (type_class)) {
11086 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11087 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11088 } else if (is_sre_type_builder (type_class)) {
11089 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11090 } else if (type->type) {
11091 gklass = mono_class_from_mono_type (type->type);
11092 gklass = mono_class_get_generic_type_definition (gklass);
11094 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11097 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11098 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11099 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11101 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11102 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11103 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11104 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11105 method = ((MonoReflectionMethod *) obj)->method;
11107 method = NULL; /* prevent compiler warning */
11108 g_error ("can't handle type %s", obj->vtable->klass->name);
11111 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11114 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11116 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11118 MonoGenericClass *gclass;
11119 MonoDynamicGenericClass *dgclass;
11120 MonoClass *klass, *gklass;
11124 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11125 klass = mono_class_from_mono_type (gtype);
11126 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11127 gclass = gtype->data.generic_class;
11129 if (!gclass->is_dynamic)
11132 dgclass = (MonoDynamicGenericClass *) gclass;
11134 if (dgclass->initialized)
11137 gklass = gclass->container_class;
11138 mono_class_init (gklass);
11140 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11142 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11143 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11144 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11146 for (i = 0; i < dgclass->count_fields; i++) {
11147 MonoObject *obj = mono_array_get (fields, gpointer, i);
11148 MonoClassField *field, *inflated_field = NULL;
11150 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11151 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11152 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11153 field = ((MonoReflectionField *) obj)->field;
11155 field = NULL; /* prevent compiler warning */
11156 g_assert_not_reached ();
11159 dgclass->fields [i] = *field;
11160 dgclass->fields [i].parent = klass;
11161 dgclass->fields [i].type = mono_class_inflate_generic_type (
11162 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11163 dgclass->field_generic_types [i] = field->type;
11164 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11165 dgclass->field_objects [i] = obj;
11167 if (inflated_field) {
11168 g_free (inflated_field);
11170 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11174 dgclass->initialized = TRUE;
11178 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11180 MonoDynamicGenericClass *dgclass;
11183 g_assert (gclass->is_dynamic);
11185 dgclass = (MonoDynamicGenericClass *)gclass;
11187 for (i = 0; i < dgclass->count_fields; ++i) {
11188 MonoClassField *field = dgclass->fields + i;
11189 mono_metadata_free_type (field->type);
11190 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11195 fix_partial_generic_class (MonoClass *klass)
11197 MonoClass *gklass = klass->generic_class->container_class;
11198 MonoDynamicGenericClass *dgclass;
11201 if (klass->wastypebuilder)
11204 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11205 if (klass->parent != gklass->parent) {
11207 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11208 if (mono_error_ok (&error)) {
11209 MonoClass *parent = mono_class_from_mono_type (parent_type);
11210 mono_metadata_free_type (parent_type);
11211 if (parent != klass->parent) {
11212 /*fool mono_class_setup_parent*/
11213 klass->supertypes = NULL;
11214 mono_class_setup_parent (klass, parent);
11217 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11218 mono_error_cleanup (&error);
11219 if (gklass->wastypebuilder)
11220 klass->wastypebuilder = TRUE;
11225 if (!dgclass->initialized)
11228 if (klass->method.count != gklass->method.count) {
11229 klass->method.count = gklass->method.count;
11230 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11232 for (i = 0; i < klass->method.count; i++) {
11234 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11235 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11236 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11240 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11241 klass->interface_count = gklass->interface_count;
11242 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11243 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11245 for (i = 0; i < gklass->interface_count; ++i) {
11246 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11247 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11248 mono_metadata_free_type (iface_type);
11250 ensure_runtime_vtable (klass->interfaces [i]);
11252 klass->interfaces_inited = 1;
11255 if (klass->field.count != gklass->field.count) {
11256 klass->field.count = gklass->field.count;
11257 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11259 for (i = 0; i < klass->field.count; i++) {
11260 klass->fields [i] = gklass->fields [i];
11261 klass->fields [i].parent = klass;
11262 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11266 /*We can only finish with this klass once it's parent has as well*/
11267 if (gklass->wastypebuilder)
11268 klass->wastypebuilder = TRUE;
11273 ensure_generic_class_runtime_vtable (MonoClass *klass)
11275 MonoClass *gklass = klass->generic_class->container_class;
11277 ensure_runtime_vtable (gklass);
11279 fix_partial_generic_class (klass);
11283 ensure_runtime_vtable (MonoClass *klass)
11285 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11288 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11291 ensure_runtime_vtable (klass->parent);
11294 num = tb->ctors? mono_array_length (tb->ctors): 0;
11295 num += tb->num_methods;
11296 klass->method.count = num;
11297 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11298 num = tb->ctors? mono_array_length (tb->ctors): 0;
11299 for (i = 0; i < num; ++i)
11300 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11301 num = tb->num_methods;
11303 for (i = 0; i < num; ++i)
11304 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11306 if (tb->interfaces) {
11307 klass->interface_count = mono_array_length (tb->interfaces);
11308 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11309 for (i = 0; i < klass->interface_count; ++i) {
11310 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11311 klass->interfaces [i] = mono_class_from_mono_type (iface);
11312 ensure_runtime_vtable (klass->interfaces [i]);
11314 klass->interfaces_inited = 1;
11316 } else if (klass->generic_class){
11317 ensure_generic_class_runtime_vtable (klass);
11320 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11322 for (i = 0; i < klass->method.count; ++i) {
11323 MonoMethod *im = klass->methods [i];
11324 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11325 im->slot = slot_num++;
11328 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11329 mono_class_setup_interface_offsets (klass);
11330 mono_class_setup_interface_id (klass);
11334 * The generic vtable is needed even if image->run is not set since some
11335 * runtime code like ves_icall_Type_GetMethodsByName depends on
11336 * method->slot being defined.
11340 * tb->methods could not be freed since it is used for determining
11341 * overrides during dynamic vtable construction.
11346 mono_reflection_method_get_handle (MonoObject *method)
11348 MonoClass *klass = mono_object_class (method);
11349 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11350 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11351 return sr_method->method;
11353 if (is_sre_method_builder (klass)) {
11354 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11355 return mb->mhandle;
11357 if (is_sre_method_on_tb_inst (klass)) {
11358 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11359 MonoMethod *result;
11360 /*FIXME move this to a proper method and unify with resolve_object*/
11361 if (m->method_args) {
11362 result = mono_reflection_method_on_tb_inst_get_handle (m);
11364 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11365 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11366 MonoMethod *mono_method;
11368 if (is_sre_method_builder (mono_object_class (m->mb)))
11369 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11370 else if (is_sr_mono_method (mono_object_class (m->mb)))
11371 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11373 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)));
11375 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11380 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11385 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11387 MonoReflectionTypeBuilder *tb;
11389 MonoReflectionMethod *m;
11392 *num_overrides = 0;
11394 g_assert (image_is_dynamic (klass->image));
11396 if (!mono_class_get_ref_info (klass))
11399 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11401 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11405 for (i = 0; i < tb->num_methods; ++i) {
11406 MonoReflectionMethodBuilder *mb =
11407 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11408 if (mb->override_methods)
11409 onum += mono_array_length (mb->override_methods);
11414 *overrides = g_new0 (MonoMethod*, onum * 2);
11417 for (i = 0; i < tb->num_methods; ++i) {
11418 MonoReflectionMethodBuilder *mb =
11419 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11420 if (mb->override_methods) {
11421 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11422 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11424 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11425 (*overrides) [onum * 2 + 1] = mb->mhandle;
11427 g_assert (mb->mhandle);
11435 *num_overrides = onum;
11439 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11441 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11442 MonoReflectionFieldBuilder *fb;
11443 MonoClassField *field;
11444 MonoImage *image = klass->image;
11445 const char *p, *p2;
11447 guint32 len, idx, real_size = 0;
11449 klass->field.count = tb->num_fields;
11450 klass->field.first = 0;
11452 mono_error_init (error);
11454 if (tb->class_size) {
11455 if ((tb->packing_size & 0xffffff00) != 0) {
11456 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11457 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11460 klass->packing_size = tb->packing_size;
11461 real_size = klass->instance_size + tb->class_size;
11464 if (!klass->field.count) {
11465 klass->instance_size = MAX (klass->instance_size, real_size);
11469 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11470 mono_class_alloc_ext (klass);
11471 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11473 This is, guess what, a hack.
11474 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11475 On the static path no field class is resolved, only types are built. This is the right thing to do
11477 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11479 klass->size_inited = 1;
11481 for (i = 0; i < klass->field.count; ++i) {
11482 MonoArray *rva_data;
11483 fb = mono_array_get (tb->fields, gpointer, i);
11484 field = &klass->fields [i];
11485 field->name = mono_string_to_utf8_image (image, fb->name, error);
11486 if (!mono_error_ok (error))
11489 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11490 field->type->attrs = fb->attrs;
11492 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11495 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11496 char *base = mono_array_addr (rva_data, char, 0);
11497 size_t size = mono_array_length (rva_data);
11498 char *data = mono_image_alloc (klass->image, size);
11499 memcpy (data, base, size);
11500 klass->ext->field_def_values [i].data = data;
11502 if (fb->offset != -1)
11503 field->offset = fb->offset;
11504 field->parent = klass;
11505 fb->handle = field;
11506 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11508 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11509 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11511 if (fb->def_value) {
11512 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11513 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11514 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11515 /* Copy the data from the blob since it might get realloc-ed */
11516 p = assembly->blob.data + idx;
11517 len = mono_metadata_decode_blob_size (p, &p2);
11519 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11520 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11524 klass->instance_size = MAX (klass->instance_size, real_size);
11525 mono_class_layout_fields (klass);
11529 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11531 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11532 MonoReflectionPropertyBuilder *pb;
11533 MonoImage *image = klass->image;
11534 MonoProperty *properties;
11537 mono_error_init (error);
11540 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11542 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11543 klass->ext->property.first = 0;
11545 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11546 klass->ext->properties = properties;
11547 for (i = 0; i < klass->ext->property.count; ++i) {
11548 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11549 properties [i].parent = klass;
11550 properties [i].attrs = pb->attrs;
11551 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11552 if (!mono_error_ok (error))
11554 if (pb->get_method)
11555 properties [i].get = pb->get_method->mhandle;
11556 if (pb->set_method)
11557 properties [i].set = pb->set_method->mhandle;
11559 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11560 if (pb->def_value) {
11562 const char *p, *p2;
11563 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11564 if (!klass->ext->prop_def_values)
11565 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11566 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11567 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11568 /* Copy the data from the blob since it might get realloc-ed */
11569 p = assembly->blob.data + idx;
11570 len = mono_metadata_decode_blob_size (p, &p2);
11572 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11573 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11578 MonoReflectionEvent *
11579 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11581 MonoEvent *event = g_new0 (MonoEvent, 1);
11584 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11586 event->parent = klass;
11587 event->attrs = eb->attrs;
11588 event->name = mono_string_to_utf8 (eb->name);
11589 if (eb->add_method)
11590 event->add = eb->add_method->mhandle;
11591 if (eb->remove_method)
11592 event->remove = eb->remove_method->mhandle;
11593 if (eb->raise_method)
11594 event->raise = eb->raise_method->mhandle;
11596 #ifndef MONO_SMALL_CONFIG
11597 if (eb->other_methods) {
11599 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11600 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11601 MonoReflectionMethodBuilder *mb =
11602 mono_array_get (eb->other_methods,
11603 MonoReflectionMethodBuilder*, j);
11604 event->other [j] = mb->mhandle;
11609 return mono_event_get_object (mono_object_domain (tb), klass, event);
11613 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11615 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11616 MonoReflectionEventBuilder *eb;
11617 MonoImage *image = klass->image;
11621 mono_error_init (error);
11624 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11626 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11627 klass->ext->event.first = 0;
11629 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11630 klass->ext->events = events;
11631 for (i = 0; i < klass->ext->event.count; ++i) {
11632 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11633 events [i].parent = klass;
11634 events [i].attrs = eb->attrs;
11635 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11636 if (!mono_error_ok (error))
11638 if (eb->add_method)
11639 events [i].add = eb->add_method->mhandle;
11640 if (eb->remove_method)
11641 events [i].remove = eb->remove_method->mhandle;
11642 if (eb->raise_method)
11643 events [i].raise = eb->raise_method->mhandle;
11645 #ifndef MONO_SMALL_CONFIG
11646 if (eb->other_methods) {
11648 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11649 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11650 MonoReflectionMethodBuilder *mb =
11651 mono_array_get (eb->other_methods,
11652 MonoReflectionMethodBuilder*, j);
11653 events [i].other [j] = mb->mhandle;
11657 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11662 remove_instantiations_of_and_ensure_contents (gpointer key,
11664 gpointer user_data)
11666 MonoType *type = (MonoType*)key;
11667 MonoClass *klass = (MonoClass*)user_data;
11669 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11670 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11677 check_array_for_usertypes (MonoArray *arr)
11684 for (i = 0; i < mono_array_length (arr); ++i)
11685 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11688 MonoReflectionType*
11689 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11693 MonoDomain* domain;
11694 MonoReflectionType* res;
11697 domain = mono_object_domain (tb);
11698 klass = mono_class_from_mono_type (tb->type.type);
11701 * Check for user defined Type subclasses.
11703 RESOLVE_TYPE (tb->parent);
11704 check_array_for_usertypes (tb->interfaces);
11706 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11707 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11709 RESOLVE_TYPE (fb->type);
11710 check_array_for_usertypes (fb->modreq);
11711 check_array_for_usertypes (fb->modopt);
11712 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11713 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11718 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11719 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11721 RESOLVE_TYPE (mb->rtype);
11722 check_array_for_usertypes (mb->return_modreq);
11723 check_array_for_usertypes (mb->return_modopt);
11724 check_array_for_usertypes (mb->parameters);
11725 if (mb->param_modreq)
11726 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11727 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11728 if (mb->param_modopt)
11729 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11730 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11735 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11736 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11738 check_array_for_usertypes (mb->parameters);
11739 if (mb->param_modreq)
11740 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11741 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11742 if (mb->param_modopt)
11743 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11744 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11749 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11752 * we need to lock the domain because the lock will be taken inside
11753 * So, we need to keep the locking order correct.
11755 mono_loader_lock ();
11756 mono_domain_lock (domain);
11757 if (klass->wastypebuilder) {
11758 mono_domain_unlock (domain);
11759 mono_loader_unlock ();
11760 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11763 * Fields to set in klass:
11764 * the various flags: delegate/unicode/contextbound etc.
11766 klass->flags = tb->attrs;
11767 klass->has_cctor = 1;
11768 klass->has_finalize = 1;
11769 klass->has_finalize_inited = 1;
11771 mono_class_setup_parent (klass, klass->parent);
11772 /* fool mono_class_setup_supertypes */
11773 klass->supertypes = NULL;
11774 mono_class_setup_supertypes (klass);
11775 mono_class_setup_mono_type (klass);
11778 if (!((MonoDynamicImage*)klass->image)->run) {
11779 if (klass->generic_container) {
11780 /* FIXME: The code below can't handle generic classes */
11781 klass->wastypebuilder = TRUE;
11782 mono_loader_unlock ();
11783 mono_domain_unlock (domain);
11784 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11789 /* enums are done right away */
11790 if (!klass->enumtype)
11791 ensure_runtime_vtable (klass);
11793 if (tb->subtypes) {
11794 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11795 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11796 mono_class_alloc_ext (klass);
11797 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)));
11801 klass->nested_classes_inited = TRUE;
11803 /* fields and object layout */
11804 if (klass->parent) {
11805 if (!klass->parent->size_inited)
11806 mono_class_init (klass->parent);
11807 klass->instance_size = klass->parent->instance_size;
11808 klass->sizes.class_size = 0;
11809 klass->min_align = klass->parent->min_align;
11810 /* if the type has no fields we won't call the field_setup
11811 * routine which sets up klass->has_references.
11813 klass->has_references |= klass->parent->has_references;
11815 klass->instance_size = sizeof (MonoObject);
11816 klass->min_align = 1;
11819 /* FIXME: handle packing_size and instance_size */
11820 typebuilder_setup_fields (klass, &error);
11821 if (!mono_error_ok (&error))
11823 typebuilder_setup_properties (klass, &error);
11824 if (!mono_error_ok (&error))
11827 typebuilder_setup_events (klass, &error);
11828 if (!mono_error_ok (&error))
11831 klass->wastypebuilder = TRUE;
11834 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11835 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11836 * we want to return normal System.MonoType objects, so clear these out from the cache.
11838 * Together with this we must ensure the contents of all instances to match the created type.
11840 if (domain->type_hash && klass->generic_container)
11841 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11843 mono_domain_unlock (domain);
11844 mono_loader_unlock ();
11846 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11847 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11848 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11851 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11852 g_assert (res != (MonoReflectionType*)tb);
11857 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11858 klass->wastypebuilder = TRUE;
11859 mono_domain_unlock (domain);
11860 mono_loader_unlock ();
11861 mono_error_raise_exception (&error);
11866 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11868 MonoGenericParamFull *param;
11873 image = &gparam->tbuilder->module->dynamic_image->image;
11875 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11877 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11878 g_assert (mono_error_ok (&error));
11879 param->param.num = gparam->index;
11881 if (gparam->mbuilder) {
11882 if (!gparam->mbuilder->generic_container) {
11883 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11884 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11885 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11886 gparam->mbuilder->generic_container->is_method = TRUE;
11888 * Cannot set owner.method, since the MonoMethod is not created yet.
11889 * Set the image field instead, so type_in_image () works.
11891 gparam->mbuilder->generic_container->image = klass->image;
11893 param->param.owner = gparam->mbuilder->generic_container;
11894 } else if (gparam->tbuilder) {
11895 if (!gparam->tbuilder->generic_container) {
11896 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11897 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11898 gparam->tbuilder->generic_container->owner.klass = klass;
11900 param->param.owner = gparam->tbuilder->generic_container;
11903 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11905 gparam->type.type = &pklass->byval_arg;
11907 mono_class_set_ref_info (pklass, gparam);
11908 mono_image_append_class_to_reflection_info_set (pklass);
11912 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11914 MonoReflectionModuleBuilder *module = sig->module;
11915 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11916 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11921 check_array_for_usertypes (sig->arguments);
11923 sigbuffer_init (&buf, 32);
11925 sigbuffer_add_value (&buf, 0x07);
11926 sigbuffer_add_value (&buf, na);
11927 if (assembly != NULL){
11928 for (i = 0; i < na; ++i) {
11929 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11930 encode_reflection_type (assembly, type, &buf);
11934 buflen = buf.p - buf.buf;
11935 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11936 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11937 sigbuffer_free (&buf);
11943 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11945 MonoDynamicImage *assembly = sig->module->dynamic_image;
11946 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11951 check_array_for_usertypes (sig->arguments);
11953 sigbuffer_init (&buf, 32);
11955 sigbuffer_add_value (&buf, 0x06);
11956 for (i = 0; i < na; ++i) {
11957 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11958 encode_reflection_type (assembly, type, &buf);
11961 buflen = buf.p - buf.buf;
11962 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11963 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11964 sigbuffer_free (&buf);
11970 MonoMethod *handle;
11971 MonoDomain *domain;
11972 } DynamicMethodReleaseData;
11975 * The runtime automatically clean up those after finalization.
11977 static MonoReferenceQueue *dynamic_method_queue;
11980 free_dynamic_method (void *dynamic_method)
11982 DynamicMethodReleaseData *data = dynamic_method;
11983 MonoDomain *domain = data->domain;
11984 MonoMethod *method = data->handle;
11987 mono_domain_lock (domain);
11988 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11989 g_hash_table_remove (domain->method_to_dyn_method, method);
11990 mono_domain_unlock (domain);
11991 g_assert (dis_link);
11992 mono_gchandle_free (dis_link);
11994 mono_runtime_free_method (domain, method);
11999 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12001 MonoReferenceQueue *queue;
12002 MonoMethod *handle;
12003 DynamicMethodReleaseData *release_data;
12004 ReflectionMethodBuilder rmb;
12005 MonoMethodSignature *sig;
12007 MonoDomain *domain;
12011 if (mono_runtime_is_shutting_down ())
12012 mono_raise_exception (mono_get_exception_invalid_operation (""));
12014 if (!(queue = dynamic_method_queue)) {
12015 mono_loader_lock ();
12016 if (!(queue = dynamic_method_queue))
12017 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12018 mono_loader_unlock ();
12021 sig = dynamic_method_to_signature (mb);
12023 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12026 * Resolve references.
12029 * Every second entry in the refs array is reserved for storing handle_class,
12030 * which is needed by the ldtoken implementation in the JIT.
12032 rmb.nrefs = mb->nrefs;
12033 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12034 for (i = 0; i < mb->nrefs; i += 2) {
12035 MonoClass *handle_class;
12037 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12039 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12040 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12042 * The referenced DynamicMethod should already be created by the managed
12043 * code, except in the case of circular references. In that case, we store
12044 * method in the refs array, and fix it up later when the referenced
12045 * DynamicMethod is created.
12047 if (method->mhandle) {
12048 ref = method->mhandle;
12050 /* FIXME: GC object stored in unmanaged memory */
12053 /* FIXME: GC object stored in unmanaged memory */
12054 method->referenced_by = g_slist_append (method->referenced_by, mb);
12056 handle_class = mono_defaults.methodhandle_class;
12058 MonoException *ex = NULL;
12059 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12061 ex = mono_get_exception_type_load (NULL, NULL);
12062 else if (mono_security_core_clr_enabled ())
12063 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12067 mono_raise_exception (ex);
12072 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12073 rmb.refs [i + 1] = handle_class;
12076 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12078 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12079 release_data = g_new (DynamicMethodReleaseData, 1);
12080 release_data->handle = handle;
12081 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12082 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12083 g_free (release_data);
12085 /* Fix up refs entries pointing at us */
12086 for (l = mb->referenced_by; l; l = l->next) {
12087 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12088 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12091 g_assert (method->mhandle);
12093 data = (gpointer*)wrapper->method_data;
12094 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12095 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12096 data [i + 1] = mb->mhandle;
12099 g_slist_free (mb->referenced_by);
12103 /* ilgen is no longer needed */
12106 domain = mono_domain_get ();
12107 mono_domain_lock (domain);
12108 if (!domain->method_to_dyn_method)
12109 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12110 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12111 mono_domain_unlock (domain);
12114 #endif /* DISABLE_REFLECTION_EMIT */
12118 * mono_reflection_is_valid_dynamic_token:
12120 * Returns TRUE if token is valid.
12124 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12126 return lookup_dyn_token (image, token) != NULL;
12129 MonoMethodSignature *
12130 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12132 MonoMethodSignature *sig;
12133 g_assert (image_is_dynamic (image));
12135 mono_error_init (error);
12137 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12141 return mono_method_signature_checked (method, error);
12144 #ifndef DISABLE_REFLECTION_EMIT
12147 * mono_reflection_lookup_dynamic_token:
12149 * Finish the Builder object pointed to by TOKEN and return the corresponding
12150 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12151 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12154 * LOCKING: Take the loader lock
12157 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12159 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12163 obj = lookup_dyn_token (assembly, token);
12166 g_error ("Could not find required dynamic token 0x%08x", token);
12172 handle_class = &klass;
12173 return resolve_object (image, obj, handle_class, context);
12177 * ensure_complete_type:
12179 * Ensure that KLASS is completed if it is a dynamic type, or references
12183 ensure_complete_type (MonoClass *klass)
12185 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12186 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12188 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12190 // Asserting here could break a lot of code
12191 //g_assert (klass->wastypebuilder);
12194 if (klass->generic_class) {
12195 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12198 for (i = 0; i < inst->type_argc; ++i) {
12199 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12205 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12207 gpointer result = NULL;
12209 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12210 result = mono_string_intern ((MonoString*)obj);
12211 *handle_class = mono_defaults.string_class;
12213 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12214 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12215 MonoClass *mc = mono_class_from_mono_type (type);
12216 if (!mono_class_init (mc))
12217 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12220 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12221 result = mono_class_from_mono_type (inflated);
12222 mono_metadata_free_type (inflated);
12224 result = mono_class_from_mono_type (type);
12226 *handle_class = mono_defaults.typehandle_class;
12228 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12229 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12230 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12231 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12232 result = ((MonoReflectionMethod*)obj)->method;
12235 result = mono_class_inflate_generic_method_checked (result, context, &error);
12236 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12238 *handle_class = mono_defaults.methodhandle_class;
12240 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12241 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12242 result = mb->mhandle;
12244 /* Type is not yet created */
12245 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12247 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12250 * Hopefully this has been filled in by calling CreateType() on the
12254 * TODO: This won't work if the application finishes another
12255 * TypeBuilder instance instead of this one.
12257 result = mb->mhandle;
12261 result = mono_class_inflate_generic_method_checked (result, context, &error);
12262 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12264 *handle_class = mono_defaults.methodhandle_class;
12265 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12266 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12268 result = cb->mhandle;
12270 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12272 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12273 result = cb->mhandle;
12277 result = mono_class_inflate_generic_method_checked (result, context, &error);
12278 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12280 *handle_class = mono_defaults.methodhandle_class;
12281 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12282 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12284 ensure_complete_type (field->parent);
12286 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12287 MonoClass *klass = mono_class_from_mono_type (inflated);
12288 MonoClassField *inflated_field;
12289 gpointer iter = NULL;
12290 mono_metadata_free_type (inflated);
12291 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12292 if (!strcmp (field->name, inflated_field->name))
12295 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12296 result = inflated_field;
12300 *handle_class = mono_defaults.fieldhandle_class;
12302 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12303 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12304 result = fb->handle;
12307 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12309 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12310 result = fb->handle;
12313 if (fb->handle && fb->handle->parent->generic_container) {
12314 MonoClass *klass = fb->handle->parent;
12315 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12316 MonoClass *inflated = mono_class_from_mono_type (type);
12318 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12320 mono_metadata_free_type (type);
12322 *handle_class = mono_defaults.fieldhandle_class;
12323 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12324 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12325 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12328 klass = type->data.klass;
12329 if (klass->wastypebuilder) {
12330 /* Already created */
12334 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12335 result = type->data.klass;
12338 *handle_class = mono_defaults.typehandle_class;
12339 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12340 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12341 MonoMethodSignature *sig;
12344 if (helper->arguments)
12345 nargs = mono_array_length (helper->arguments);
12349 sig = mono_metadata_signature_alloc (image, nargs);
12350 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12351 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12353 if (helper->unmanaged_call_conv) { /* unmanaged */
12354 sig->call_convention = helper->unmanaged_call_conv - 1;
12355 sig->pinvoke = TRUE;
12356 } else if (helper->call_conv & 0x02) {
12357 sig->call_convention = MONO_CALL_VARARG;
12359 sig->call_convention = MONO_CALL_DEFAULT;
12362 sig->param_count = nargs;
12363 /* TODO: Copy type ? */
12364 sig->ret = helper->return_type->type;
12365 for (i = 0; i < nargs; ++i)
12366 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12369 *handle_class = NULL;
12370 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12371 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12372 /* Already created by the managed code */
12373 g_assert (method->mhandle);
12374 result = method->mhandle;
12375 *handle_class = mono_defaults.methodhandle_class;
12376 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12377 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12378 type = mono_class_inflate_generic_type (type, context);
12379 result = mono_class_from_mono_type (type);
12380 *handle_class = mono_defaults.typehandle_class;
12382 mono_metadata_free_type (type);
12383 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12384 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12385 type = mono_class_inflate_generic_type (type, context);
12386 result = mono_class_from_mono_type (type);
12387 *handle_class = mono_defaults.typehandle_class;
12389 mono_metadata_free_type (type);
12390 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12391 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12392 MonoClass *inflated;
12394 MonoClassField *field;
12396 if (is_sre_field_builder (mono_object_class (f->fb)))
12397 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12398 else if (is_sr_mono_field (mono_object_class (f->fb)))
12399 field = ((MonoReflectionField*)f->fb)->field;
12401 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)));
12403 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12404 inflated = mono_class_from_mono_type (type);
12406 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12407 ensure_complete_type (field->parent);
12409 mono_metadata_free_type (type);
12410 *handle_class = mono_defaults.fieldhandle_class;
12411 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12412 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12413 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12414 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12415 MonoMethod *method;
12417 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12418 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12419 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12420 method = ((MonoReflectionMethod *)c->cb)->method;
12422 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)));
12424 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12425 *handle_class = mono_defaults.methodhandle_class;
12426 mono_metadata_free_type (type);
12427 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12428 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12429 if (m->method_args) {
12430 result = mono_reflection_method_on_tb_inst_get_handle (m);
12433 result = mono_class_inflate_generic_method_checked (result, context, &error);
12434 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12437 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12438 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12439 MonoMethod *method;
12441 if (is_sre_method_builder (mono_object_class (m->mb)))
12442 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12443 else if (is_sr_mono_method (mono_object_class (m->mb)))
12444 method = ((MonoReflectionMethod *)m->mb)->method;
12446 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)));
12448 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12449 mono_metadata_free_type (type);
12451 *handle_class = mono_defaults.methodhandle_class;
12452 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12453 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12456 MonoMethod *method;
12460 mtype = mono_reflection_type_get_handle (m->parent);
12461 klass = mono_class_from_mono_type (mtype);
12463 /* Find the method */
12465 name = mono_string_to_utf8 (m->name);
12467 while ((method = mono_class_get_methods (klass, &iter))) {
12468 if (!strcmp (method->name, name))
12475 // FIXME: Check parameters/return value etc. match
12478 *handle_class = mono_defaults.methodhandle_class;
12479 } else if (is_sre_array (mono_object_get_class(obj)) ||
12480 is_sre_byref (mono_object_get_class(obj)) ||
12481 is_sre_pointer (mono_object_get_class(obj))) {
12482 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12483 MonoType *type = mono_reflection_type_get_handle (ref_type);
12486 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12487 result = mono_class_from_mono_type (inflated);
12488 mono_metadata_free_type (inflated);
12490 result = mono_class_from_mono_type (type);
12492 *handle_class = mono_defaults.typehandle_class;
12494 g_print ("%s\n", obj->vtable->klass->name);
12495 g_assert_not_reached ();
12500 #else /* DISABLE_REFLECTION_EMIT */
12503 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12505 g_assert_not_reached ();
12510 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12512 g_assert_not_reached ();
12516 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12518 g_assert_not_reached ();
12522 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12524 g_assert_not_reached ();
12528 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12530 g_assert_not_reached ();
12534 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12536 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12540 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12542 g_assert_not_reached ();
12546 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12548 g_assert_not_reached ();
12551 MonoReflectionModule *
12552 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12554 g_assert_not_reached ();
12559 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12561 g_assert_not_reached ();
12566 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12568 g_assert_not_reached ();
12573 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12574 gboolean create_open_instance, gboolean register_token)
12576 g_assert_not_reached ();
12581 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12586 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12588 g_assert_not_reached ();
12592 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12595 *num_overrides = 0;
12598 MonoReflectionEvent *
12599 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12601 g_assert_not_reached ();
12605 MonoReflectionType*
12606 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12608 g_assert_not_reached ();
12613 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12615 g_assert_not_reached ();
12619 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12621 g_assert_not_reached ();
12626 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12628 g_assert_not_reached ();
12633 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12638 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12644 mono_reflection_type_get_handle (MonoReflectionType* ref)
12652 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12654 g_assert_not_reached ();
12657 #endif /* DISABLE_REFLECTION_EMIT */
12659 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12660 const static guint32 declsec_flags_map[] = {
12661 0x00000000, /* empty */
12662 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12663 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12664 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12665 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12666 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12667 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12668 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12669 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12670 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12671 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12672 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12673 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12674 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12675 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12676 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12677 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12678 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12679 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12683 * Returns flags that includes all available security action associated to the handle.
12684 * @token: metadata token (either for a class or a method)
12685 * @image: image where resides the metadata.
12688 mono_declsec_get_flags (MonoImage *image, guint32 token)
12690 int index = mono_metadata_declsec_from_index (image, token);
12691 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12692 guint32 result = 0;
12696 /* HasSecurity can be present for other, not specially encoded, attributes,
12697 e.g. SuppressUnmanagedCodeSecurityAttribute */
12701 for (i = index; i < t->rows; i++) {
12702 guint32 cols [MONO_DECL_SECURITY_SIZE];
12704 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12705 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12708 action = cols [MONO_DECL_SECURITY_ACTION];
12709 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12710 result |= declsec_flags_map [action];
12712 g_assert_not_reached ();
12719 * Get the security actions (in the form of flags) associated with the specified method.
12721 * @method: The method for which we want the declarative security flags.
12722 * Return the declarative security flags for the method (only).
12724 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12725 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12728 mono_declsec_flags_from_method (MonoMethod *method)
12730 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12731 /* FIXME: No cache (for the moment) */
12732 guint32 idx = mono_method_get_index (method);
12733 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12734 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12735 return mono_declsec_get_flags (method->klass->image, idx);
12741 * Get the security actions (in the form of flags) associated with the specified class.
12743 * @klass: The class for which we want the declarative security flags.
12744 * Return the declarative security flags for the class.
12746 * Note: We cache the flags inside the MonoClass structure as this will get
12747 * called very often (at least for each method).
12750 mono_declsec_flags_from_class (MonoClass *klass)
12752 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12753 if (!klass->ext || !klass->ext->declsec_flags) {
12756 idx = mono_metadata_token_index (klass->type_token);
12757 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12758 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12759 mono_loader_lock ();
12760 mono_class_alloc_ext (klass);
12761 mono_loader_unlock ();
12762 /* we cache the flags on classes */
12763 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12765 return klass->ext->declsec_flags;
12771 * Get the security actions (in the form of flags) associated with the specified assembly.
12773 * @assembly: The assembly for which we want the declarative security flags.
12774 * Return the declarative security flags for the assembly.
12777 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12779 guint32 idx = 1; /* there is only one assembly */
12780 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12781 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12782 return mono_declsec_get_flags (assembly->image, idx);
12787 * Fill actions for the specific index (which may either be an encoded class token or
12788 * an encoded method token) from the metadata image.
12789 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12792 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12793 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12795 MonoBoolean result = FALSE;
12797 guint32 cols [MONO_DECL_SECURITY_SIZE];
12798 int index = mono_metadata_declsec_from_index (image, token);
12801 t = &image->tables [MONO_TABLE_DECLSECURITY];
12802 for (i = index; i < t->rows; i++) {
12803 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12805 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12808 /* if present only replace (class) permissions with method permissions */
12809 /* if empty accept either class or method permissions */
12810 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12811 if (!actions->demand.blob) {
12812 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12813 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12814 actions->demand.blob = (char*) (blob + 2);
12815 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12818 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12819 if (!actions->noncasdemand.blob) {
12820 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12821 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12822 actions->noncasdemand.blob = (char*) (blob + 2);
12823 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12826 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12827 if (!actions->demandchoice.blob) {
12828 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12829 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12830 actions->demandchoice.blob = (char*) (blob + 2);
12831 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12841 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12842 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12844 guint32 idx = mono_metadata_token_index (klass->type_token);
12845 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12846 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12847 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12851 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12852 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12854 guint32 idx = mono_method_get_index (method);
12855 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12856 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12857 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12861 * Collect all actions (that requires to generate code in mini) assigned for
12862 * the specified method.
12863 * Note: Don't use the content of actions if the function return FALSE.
12866 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12868 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12869 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12870 MonoBoolean result = FALSE;
12873 /* quick exit if no declarative security is present in the metadata */
12874 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12877 /* we want the original as the wrapper is "free" of the security informations */
12878 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12879 method = mono_marshal_method_from_wrapper (method);
12884 /* First we look for method-level attributes */
12885 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12886 mono_class_init (method->klass);
12887 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12889 result = mono_declsec_get_method_demands_params (method, demands,
12890 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12893 /* Here we use (or create) the class declarative cache to look for demands */
12894 flags = mono_declsec_flags_from_class (method->klass);
12895 if (flags & mask) {
12897 mono_class_init (method->klass);
12898 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12900 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12901 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12904 /* The boolean return value is used as a shortcut in case nothing needs to
12905 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12911 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12913 * Note: Don't use the content of actions if the function return FALSE.
12916 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12918 MonoBoolean result = FALSE;
12921 /* quick exit if no declarative security is present in the metadata */
12922 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12925 /* we want the original as the wrapper is "free" of the security informations */
12926 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12927 method = mono_marshal_method_from_wrapper (method);
12932 /* results are independant - zeroize both */
12933 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12934 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12936 /* First we look for method-level attributes */
12937 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12938 mono_class_init (method->klass);
12940 result = mono_declsec_get_method_demands_params (method, cmethod,
12941 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12944 /* Here we use (or create) the class declarative cache to look for demands */
12945 flags = mono_declsec_flags_from_class (method->klass);
12946 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12947 mono_class_init (method->klass);
12949 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12950 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12957 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12959 * @klass The inherited class - this is the class that provides the security check (attributes)
12961 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12963 * Note: Don't use the content of actions if the function return FALSE.
12966 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12968 MonoBoolean result = FALSE;
12971 /* quick exit if no declarative security is present in the metadata */
12972 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12975 /* Here we use (or create) the class declarative cache to look for demands */
12976 flags = mono_declsec_flags_from_class (klass);
12977 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12978 mono_class_init (klass);
12979 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12981 result |= mono_declsec_get_class_demands_params (klass, demands,
12982 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12989 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12991 * Note: Don't use the content of actions if the function return FALSE.
12994 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12996 /* quick exit if no declarative security is present in the metadata */
12997 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13000 /* we want the original as the wrapper is "free" of the security informations */
13001 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13002 method = mono_marshal_method_from_wrapper (method);
13007 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13008 mono_class_init (method->klass);
13009 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13011 return mono_declsec_get_method_demands_params (method, demands,
13012 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13019 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13021 guint32 cols [MONO_DECL_SECURITY_SIZE];
13025 int index = mono_metadata_declsec_from_index (image, token);
13029 t = &image->tables [MONO_TABLE_DECLSECURITY];
13030 for (i = index; i < t->rows; i++) {
13031 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13033 /* shortcut - index are ordered */
13034 if (token != cols [MONO_DECL_SECURITY_PARENT])
13037 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13038 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13039 entry->blob = (char*) (metadata + 2);
13040 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13049 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13051 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13052 guint32 idx = mono_method_get_index (method);
13053 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13054 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13055 return get_declsec_action (method->klass->image, idx, action, entry);
13061 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13064 guint32 flags = mono_declsec_flags_from_class (klass);
13065 if (declsec_flags_map [action] & flags) {
13066 guint32 idx = mono_metadata_token_index (klass->type_token);
13067 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13068 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13069 return get_declsec_action (klass->image, idx, action, entry);
13075 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13077 guint32 idx = 1; /* there is only one assembly */
13078 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13079 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13081 return get_declsec_action (assembly->image, idx, action, entry);
13085 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13087 MonoObject *res, *exc;
13089 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13090 static MonoMethod *method = NULL;
13092 if (!System_Reflection_Emit_TypeBuilder) {
13093 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13094 g_assert (System_Reflection_Emit_TypeBuilder);
13096 if (method == NULL) {
13097 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13102 * The result of mono_type_get_object () might be a System.MonoType but we
13103 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13105 g_assert (mono_class_get_ref_info (klass));
13106 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13108 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13110 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13114 return *(MonoBoolean*)mono_object_unbox (res);
13118 * mono_reflection_type_get_type:
13119 * @reftype: the System.Type object
13121 * Returns the MonoType* associated with the C# System.Type object @reftype.
13124 mono_reflection_type_get_type (MonoReflectionType *reftype)
13126 g_assert (reftype);
13128 return mono_reflection_type_get_handle (reftype);
13132 * mono_reflection_assembly_get_assembly:
13133 * @refassembly: the System.Reflection.Assembly object
13135 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13138 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13140 g_assert (refassembly);
13142 return refassembly->assembly;