2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
74 guint32 *table_idx; /* note: it's a pointer */
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
174 static gboolean is_sre_array (MonoClass *class);
175 static gboolean is_sre_byref (MonoClass *class);
176 static gboolean is_sre_pointer (MonoClass *class);
177 static gboolean is_sre_type_builder (MonoClass *class);
178 static gboolean is_sre_method_builder (MonoClass *class);
179 static gboolean is_sre_ctor_builder (MonoClass *class);
180 static gboolean is_sre_field_builder (MonoClass *class);
181 static gboolean is_sr_mono_method (MonoClass *class);
182 static gboolean is_sr_mono_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_generic_method (MonoClass *class);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
185 static gboolean is_sr_mono_field (MonoClass *class);
186 static gboolean is_sr_mono_property (MonoClass *class);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
199 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
200 __type = mono_reflection_type_resolve_user_types (__type); \
201 mono_array_set (arr, MonoReflectionType*, index, __type); \
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220 mono_reflection_init (void)
225 dynamic_image_lock (MonoDynamicImage *image)
228 mono_image_lock ((MonoImage*)image);
229 MONO_FINISH_TRY_BLOCKING;
233 dynamic_image_unlock (MonoDynamicImage *image)
235 mono_image_unlock ((MonoImage*)image);
239 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
241 MONO_REQ_GC_UNSAFE_MODE;
243 dynamic_image_lock (assembly);
244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
245 dynamic_image_unlock (assembly);
249 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
251 MONO_REQ_GC_UNSAFE_MODE;
255 dynamic_image_lock (assembly);
256 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
257 dynamic_image_unlock (assembly);
263 sigbuffer_init (SigBuffer *buf, int size)
265 MONO_REQ_GC_NEUTRAL_MODE;
267 buf->buf = g_malloc (size);
269 buf->end = buf->buf + size;
273 sigbuffer_make_room (SigBuffer *buf, int size)
275 MONO_REQ_GC_NEUTRAL_MODE;
277 if (buf->end - buf->p < size) {
278 int new_size = buf->end - buf->buf + size + 32;
279 char *p = g_realloc (buf->buf, new_size);
280 size = buf->p - buf->buf;
283 buf->end = buf->buf + new_size;
288 sigbuffer_add_value (SigBuffer *buf, guint32 val)
290 MONO_REQ_GC_NEUTRAL_MODE;
292 sigbuffer_make_room (buf, 6);
293 mono_metadata_encode_value (val, buf->p, &buf->p);
297 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
299 MONO_REQ_GC_NEUTRAL_MODE;
301 sigbuffer_make_room (buf, 1);
307 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
309 MONO_REQ_GC_NEUTRAL_MODE;
311 sigbuffer_make_room (buf, size);
312 memcpy (buf->p, p, size);
317 sigbuffer_free (SigBuffer *buf)
319 MONO_REQ_GC_NEUTRAL_MODE;
324 #ifndef DISABLE_REFLECTION_EMIT
328 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
332 image_g_malloc (MonoImage *image, guint size)
334 MONO_REQ_GC_NEUTRAL_MODE;
337 return mono_image_alloc (image, size);
339 return g_malloc (size);
341 #endif /* !DISABLE_REFLECTION_EMIT */
346 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
350 image_g_malloc0 (MonoImage *image, guint size)
352 MONO_REQ_GC_NEUTRAL_MODE;
355 return mono_image_alloc0 (image, size);
357 return g_malloc0 (size);
360 #ifndef DISABLE_REFLECTION_EMIT
362 image_strdup (MonoImage *image, const char *s)
364 MONO_REQ_GC_NEUTRAL_MODE;
367 return mono_image_strdup (image, s);
373 #define image_g_new(image,struct_type, n_structs) \
374 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
376 #define image_g_new0(image,struct_type, n_structs) \
377 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
381 alloc_table (MonoDynamicTable *table, guint nrows)
383 MONO_REQ_GC_NEUTRAL_MODE;
386 g_assert (table->columns);
387 if (nrows + 1 >= table->alloc_rows) {
388 while (nrows + 1 >= table->alloc_rows) {
389 if (table->alloc_rows == 0)
390 table->alloc_rows = 16;
392 table->alloc_rows *= 2;
395 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
400 make_room_in_stream (MonoDynamicStream *stream, int size)
402 MONO_REQ_GC_NEUTRAL_MODE;
404 if (size <= stream->alloc_size)
407 while (stream->alloc_size <= size) {
408 if (stream->alloc_size < 4096)
409 stream->alloc_size = 4096;
411 stream->alloc_size *= 2;
414 stream->data = g_realloc (stream->data, stream->alloc_size);
418 string_heap_insert (MonoDynamicStream *sh, const char *str)
420 MONO_REQ_GC_NEUTRAL_MODE;
424 gpointer oldkey, oldval;
426 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
427 return GPOINTER_TO_UINT (oldval);
429 len = strlen (str) + 1;
432 make_room_in_stream (sh, idx + len);
435 * We strdup the string even if we already copy them in sh->data
436 * so that the string pointers in the hash remain valid even if
437 * we need to realloc sh->data. We may want to avoid that later.
439 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
440 memcpy (sh->data + idx, str, len);
446 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
448 MONO_REQ_GC_UNSAFE_MODE;
450 char *name = mono_string_to_utf8 (str);
452 idx = string_heap_insert (sh, name);
457 #ifndef DISABLE_REFLECTION_EMIT
459 string_heap_init (MonoDynamicStream *sh)
461 MONO_REQ_GC_NEUTRAL_MODE;
464 sh->alloc_size = 4096;
465 sh->data = g_malloc (4096);
466 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
467 string_heap_insert (sh, "");
472 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
474 MONO_REQ_GC_NEUTRAL_MODE;
478 make_room_in_stream (stream, stream->index + len);
479 memcpy (stream->data + stream->index, data, len);
481 stream->index += len;
483 * align index? Not without adding an additional param that controls it since
484 * we may store a blob value in pieces.
490 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
492 MONO_REQ_GC_NEUTRAL_MODE;
496 make_room_in_stream (stream, stream->index + len);
497 memset (stream->data + stream->index, 0, len);
499 stream->index += len;
504 stream_data_align (MonoDynamicStream *stream)
506 MONO_REQ_GC_NEUTRAL_MODE;
509 guint32 count = stream->index % 4;
511 /* we assume the stream data will be aligned */
513 mono_image_add_stream_data (stream, buf, 4 - count);
516 #ifndef DISABLE_REFLECTION_EMIT
518 mono_blob_entry_hash (const char* str)
520 MONO_REQ_GC_NEUTRAL_MODE;
524 len = mono_metadata_decode_blob_size (str, &str);
528 for (str += 1; str < end; str++)
529 h = (h << 5) - h + *str;
537 mono_blob_entry_equal (const char *str1, const char *str2) {
538 MONO_REQ_GC_NEUTRAL_MODE;
543 len = mono_metadata_decode_blob_size (str1, &end1);
544 len2 = mono_metadata_decode_blob_size (str2, &end2);
547 return memcmp (end1, end2, len) == 0;
551 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
553 MONO_REQ_GC_NEUTRAL_MODE;
557 gpointer oldkey, oldval;
559 copy = g_malloc (s1+s2);
560 memcpy (copy, b1, s1);
561 memcpy (copy + s1, b2, s2);
562 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
564 idx = GPOINTER_TO_UINT (oldval);
566 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
567 mono_image_add_stream_data (&assembly->blob, b2, s2);
568 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
574 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
576 MONO_REQ_GC_NEUTRAL_MODE;
580 guint32 size = buf->p - buf->buf;
582 g_assert (size <= (buf->end - buf->buf));
583 mono_metadata_encode_value (size, b, &b);
584 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
588 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
589 * dest may be misaligned.
592 swap_with_size (char *dest, const char* val, int len, int nelem) {
593 MONO_REQ_GC_NEUTRAL_MODE;
594 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
597 for (elem = 0; elem < nelem; ++elem) {
623 g_assert_not_reached ();
629 memcpy (dest, val, len * nelem);
634 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
636 MONO_REQ_GC_UNSAFE_MODE;
640 guint32 idx = 0, len;
642 len = str->length * 2;
643 mono_metadata_encode_value (len, b, &b);
644 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
646 char *swapped = g_malloc (2 * mono_string_length (str));
647 const char *p = (const char*)mono_string_chars (str);
649 swap_with_size (swapped, p, 2, mono_string_length (str));
650 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
654 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
659 #ifndef DISABLE_REFLECTION_EMIT
661 default_class_from_mono_type (MonoType *type)
663 MONO_REQ_GC_NEUTRAL_MODE;
665 switch (type->type) {
666 case MONO_TYPE_OBJECT:
667 return mono_defaults.object_class;
669 return mono_defaults.void_class;
670 case MONO_TYPE_BOOLEAN:
671 return mono_defaults.boolean_class;
673 return mono_defaults.char_class;
675 return mono_defaults.sbyte_class;
677 return mono_defaults.byte_class;
679 return mono_defaults.int16_class;
681 return mono_defaults.uint16_class;
683 return mono_defaults.int32_class;
685 return mono_defaults.uint32_class;
687 return mono_defaults.int_class;
689 return mono_defaults.uint_class;
691 return mono_defaults.int64_class;
693 return mono_defaults.uint64_class;
695 return mono_defaults.single_class;
697 return mono_defaults.double_class;
698 case MONO_TYPE_STRING:
699 return mono_defaults.string_class;
701 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
702 g_assert_not_reached ();
710 * mono_class_get_ref_info:
712 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
715 mono_class_get_ref_info (MonoClass *klass)
717 MONO_REQ_GC_UNSAFE_MODE;
719 if (klass->ref_info_handle == 0)
722 return mono_gchandle_get_target (klass->ref_info_handle);
726 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
728 MONO_REQ_GC_UNSAFE_MODE;
730 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
731 g_assert (klass->ref_info_handle != 0);
735 mono_class_free_ref_info (MonoClass *klass)
737 MONO_REQ_GC_NEUTRAL_MODE;
739 if (klass->ref_info_handle) {
740 mono_gchandle_free (klass->ref_info_handle);
741 klass->ref_info_handle = 0;
746 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
748 MONO_REQ_GC_NEUTRAL_MODE;
751 MonoGenericInst *class_inst;
756 class_inst = gclass->context.class_inst;
758 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
759 klass = gclass->container_class;
760 sigbuffer_add_value (buf, klass->byval_arg.type);
761 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
763 sigbuffer_add_value (buf, class_inst->type_argc);
764 for (i = 0; i < class_inst->type_argc; ++i)
765 encode_type (assembly, class_inst->type_argv [i], buf);
770 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
772 MONO_REQ_GC_NEUTRAL_MODE;
775 g_assert_not_reached ();
780 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
784 case MONO_TYPE_BOOLEAN:
798 case MONO_TYPE_STRING:
799 case MONO_TYPE_OBJECT:
800 case MONO_TYPE_TYPEDBYREF:
801 sigbuffer_add_value (buf, type->type);
804 sigbuffer_add_value (buf, type->type);
805 encode_type (assembly, type->data.type, buf);
807 case MONO_TYPE_SZARRAY:
808 sigbuffer_add_value (buf, type->type);
809 encode_type (assembly, &type->data.klass->byval_arg, buf);
811 case MONO_TYPE_VALUETYPE:
812 case MONO_TYPE_CLASS: {
813 MonoClass *k = mono_class_from_mono_type (type);
815 if (k->generic_container) {
816 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
817 encode_generic_class (assembly, gclass, buf);
820 * Make sure we use the correct type.
822 sigbuffer_add_value (buf, k->byval_arg.type);
824 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
825 * otherwise two typerefs could point to the same type, leading to
826 * verification errors.
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
832 case MONO_TYPE_ARRAY:
833 sigbuffer_add_value (buf, type->type);
834 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
835 sigbuffer_add_value (buf, type->data.array->rank);
836 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
837 sigbuffer_add_value (buf, 0);
839 case MONO_TYPE_GENERICINST:
840 encode_generic_class (assembly, type->data.generic_class, buf);
844 sigbuffer_add_value (buf, type->type);
845 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
848 g_error ("need to encode type %x", type->type);
853 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
855 MONO_REQ_GC_UNSAFE_MODE;
858 sigbuffer_add_value (buf, MONO_TYPE_VOID);
862 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
866 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
868 MONO_REQ_GC_UNSAFE_MODE;
873 for (i = 0; i < mono_array_length (modreq); ++i) {
874 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
875 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
876 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
880 for (i = 0; i < mono_array_length (modopt); ++i) {
881 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
882 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
883 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
888 #ifndef DISABLE_REFLECTION_EMIT
890 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
892 MONO_REQ_GC_UNSAFE_MODE;
896 guint32 nparams = sig->param_count;
902 sigbuffer_init (&buf, 32);
904 * FIXME: vararg, explicit_this, differenc call_conv values...
906 idx = sig->call_convention;
908 idx |= 0x20; /* hasthis */
909 if (sig->generic_param_count)
910 idx |= 0x10; /* generic */
911 sigbuffer_add_byte (&buf, idx);
912 if (sig->generic_param_count)
913 sigbuffer_add_value (&buf, sig->generic_param_count);
914 sigbuffer_add_value (&buf, nparams);
915 encode_type (assembly, sig->ret, &buf);
916 for (i = 0; i < nparams; ++i) {
917 if (i == sig->sentinelpos)
918 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
919 encode_type (assembly, sig->params [i], &buf);
921 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
922 sigbuffer_free (&buf);
928 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
930 MONO_REQ_GC_UNSAFE_MODE;
933 * FIXME: reuse code from method_encode_signature().
937 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
938 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
939 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
942 sigbuffer_init (&buf, 32);
943 /* LAMESPEC: all the call conv spec is foobared */
944 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
945 if (mb->call_conv & 2)
946 idx |= 0x5; /* vararg */
947 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
948 idx |= 0x20; /* hasthis */
950 idx |= 0x10; /* generic */
951 sigbuffer_add_byte (&buf, idx);
953 sigbuffer_add_value (&buf, ngparams);
954 sigbuffer_add_value (&buf, nparams + notypes);
955 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
956 encode_reflection_type (assembly, mb->rtype, &buf);
957 for (i = 0; i < nparams; ++i) {
958 MonoArray *modreq = NULL;
959 MonoArray *modopt = NULL;
960 MonoReflectionType *pt;
962 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
963 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
964 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
965 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
966 encode_custom_modifiers (assembly, modreq, modopt, &buf);
967 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
968 encode_reflection_type (assembly, pt, &buf);
971 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
972 for (i = 0; i < notypes; ++i) {
973 MonoReflectionType *pt;
975 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
976 encode_reflection_type (assembly, pt, &buf);
979 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
980 sigbuffer_free (&buf);
985 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
987 MONO_REQ_GC_UNSAFE_MODE;
989 MonoDynamicTable *table;
991 guint32 idx, sig_idx;
992 guint nl = mono_array_length (ilgen->locals);
996 sigbuffer_init (&buf, 32);
997 sigbuffer_add_value (&buf, 0x07);
998 sigbuffer_add_value (&buf, nl);
999 for (i = 0; i < nl; ++i) {
1000 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1003 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1005 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1007 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1008 sigbuffer_free (&buf);
1010 if (assembly->standalonesig_cache == NULL)
1011 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1012 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1016 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1017 idx = table->next_idx ++;
1019 alloc_table (table, table->rows);
1020 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1022 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1024 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1030 method_count_clauses (MonoReflectionILGen *ilgen)
1032 MONO_REQ_GC_UNSAFE_MODE;
1034 guint32 num_clauses = 0;
1037 MonoILExceptionInfo *ex_info;
1038 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1039 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1040 if (ex_info->handlers)
1041 num_clauses += mono_array_length (ex_info->handlers);
1049 #ifndef DISABLE_REFLECTION_EMIT
1050 static MonoExceptionClause*
1051 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1053 MONO_REQ_GC_UNSAFE_MODE;
1055 MonoExceptionClause *clauses;
1056 MonoExceptionClause *clause;
1057 MonoILExceptionInfo *ex_info;
1058 MonoILExceptionBlock *ex_block;
1059 guint32 finally_start;
1060 int i, j, clause_index;;
1062 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1065 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1066 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1067 finally_start = ex_info->start + ex_info->len;
1068 if (!ex_info->handlers)
1070 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1071 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1072 clause = &(clauses [clause_index]);
1074 clause->flags = ex_block->type;
1075 clause->try_offset = ex_info->start;
1077 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1078 clause->try_len = finally_start - ex_info->start;
1080 clause->try_len = ex_info->len;
1081 clause->handler_offset = ex_block->start;
1082 clause->handler_len = ex_block->len;
1083 if (ex_block->extype) {
1084 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1086 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1087 clause->data.filter_offset = ex_block->filter_offset;
1089 clause->data.filter_offset = 0;
1091 finally_start = ex_block->start + ex_block->len;
1099 #endif /* !DISABLE_REFLECTION_EMIT */
1102 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1104 MONO_REQ_GC_UNSAFE_MODE;
1109 gint32 max_stack, i;
1110 gint32 num_locals = 0;
1111 gint32 num_exception = 0;
1114 char fat_header [12];
1116 guint16 short_value;
1117 guint32 local_sig = 0;
1118 guint32 header_size = 12;
1121 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1122 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1126 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1128 code = mb->ilgen->code;
1129 code_size = mb->ilgen->code_len;
1130 max_stack = mb->ilgen->max_stack;
1131 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1132 if (mb->ilgen->ex_handlers)
1133 num_exception = method_count_clauses (mb->ilgen);
1137 char *name = mono_string_to_utf8 (mb->name);
1138 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1139 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1142 mono_raise_exception (exception);
1145 code_size = mono_array_length (code);
1146 max_stack = 8; /* we probably need to run a verifier on the code... */
1149 stream_data_align (&assembly->code);
1151 /* check for exceptions, maxstack, locals */
1152 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1154 if (code_size < 64 && !(code_size & 1)) {
1155 flags = (code_size << 2) | 0x2;
1156 } else if (code_size < 32 && (code_size & 1)) {
1157 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1161 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1162 /* add to the fixup todo list */
1163 if (mb->ilgen && mb->ilgen->num_token_fixups)
1164 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1165 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1166 return assembly->text_rva + idx;
1170 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1172 * FIXME: need to set also the header size in fat_flags.
1173 * (and more sects and init locals flags)
1177 fat_flags |= METHOD_HEADER_MORE_SECTS;
1178 if (mb->init_locals)
1179 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1180 fat_header [0] = fat_flags;
1181 fat_header [1] = (header_size / 4 ) << 4;
1182 short_value = GUINT16_TO_LE (max_stack);
1183 memcpy (fat_header + 2, &short_value, 2);
1184 int_value = GUINT32_TO_LE (code_size);
1185 memcpy (fat_header + 4, &int_value, 4);
1186 int_value = GUINT32_TO_LE (local_sig);
1187 memcpy (fat_header + 8, &int_value, 4);
1188 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1189 /* add to the fixup todo list */
1190 if (mb->ilgen && mb->ilgen->num_token_fixups)
1191 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1193 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1194 if (num_exception) {
1195 unsigned char sheader [4];
1196 MonoILExceptionInfo * ex_info;
1197 MonoILExceptionBlock * ex_block;
1200 stream_data_align (&assembly->code);
1201 /* always use fat format for now */
1202 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1203 num_exception *= 6 * sizeof (guint32);
1204 num_exception += 4; /* include the size of the header */
1205 sheader [1] = num_exception & 0xff;
1206 sheader [2] = (num_exception >> 8) & 0xff;
1207 sheader [3] = (num_exception >> 16) & 0xff;
1208 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1209 /* fat header, so we are already aligned */
1211 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1212 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1213 if (ex_info->handlers) {
1214 int finally_start = ex_info->start + ex_info->len;
1215 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1217 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1219 val = GUINT32_TO_LE (ex_block->type);
1220 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1222 val = GUINT32_TO_LE (ex_info->start);
1223 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1224 /* need fault, too, probably */
1225 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1226 val = GUINT32_TO_LE (finally_start - ex_info->start);
1228 val = GUINT32_TO_LE (ex_info->len);
1229 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1230 /* handler offset */
1231 val = GUINT32_TO_LE (ex_block->start);
1232 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1234 val = GUINT32_TO_LE (ex_block->len);
1235 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1236 finally_start = ex_block->start + ex_block->len;
1237 if (ex_block->extype) {
1238 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1240 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1241 val = ex_block->filter_offset;
1245 val = GUINT32_TO_LE (val);
1246 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1247 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1248 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1251 g_error ("No clauses for ex info block %d", i);
1255 return assembly->text_rva + idx;
1259 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1261 MONO_REQ_GC_NEUTRAL_MODE;
1264 MonoDynamicTable *table;
1267 table = &assembly->tables [table_idx];
1269 g_assert (col < table->columns);
1271 values = table->values + table->columns;
1272 for (i = 1; i <= table->rows; ++i) {
1273 if (values [col] == token)
1275 values += table->columns;
1281 * LOCKING: Acquires the loader lock.
1283 static MonoCustomAttrInfo*
1284 lookup_custom_attr (MonoImage *image, gpointer member)
1286 MONO_REQ_GC_NEUTRAL_MODE;
1288 MonoCustomAttrInfo* res;
1290 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1295 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1301 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1303 MONO_REQ_GC_UNSAFE_MODE;
1305 /* FIXME: Need to do more checks */
1306 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1307 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1309 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1316 static MonoCustomAttrInfo*
1317 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1319 MONO_REQ_GC_UNSAFE_MODE;
1321 int i, index, count, not_visible;
1322 MonoCustomAttrInfo *ainfo;
1323 MonoReflectionCustomAttr *cattr;
1327 /* FIXME: check in assembly the Run flag is set */
1329 count = mono_array_length (cattrs);
1331 /* Skip nonpublic attributes since MS.NET seems to do the same */
1332 /* FIXME: This needs to be done more globally */
1334 for (i = 0; i < count; ++i) {
1335 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1336 if (!custom_attr_visible (image, cattr))
1339 count -= not_visible;
1341 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1343 ainfo->image = image;
1344 ainfo->num_attrs = count;
1345 ainfo->cached = alloc_img != NULL;
1347 for (i = 0; i < count; ++i) {
1348 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1349 if (custom_attr_visible (image, cattr)) {
1350 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1351 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1352 ainfo->attrs [index].ctor = cattr->ctor->method;
1353 ainfo->attrs [index].data = saved;
1354 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1362 #ifndef DISABLE_REFLECTION_EMIT
1364 * LOCKING: Acquires the loader lock.
1367 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1369 MONO_REQ_GC_UNSAFE_MODE;
1371 MonoCustomAttrInfo *ainfo, *tmp;
1373 if (!cattrs || !mono_array_length (cattrs))
1376 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1378 mono_loader_lock ();
1379 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1381 mono_custom_attrs_free (tmp);
1382 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1383 mono_loader_unlock ();
1389 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1391 MONO_REQ_GC_NEUTRAL_MODE;
1398 * idx is the table index of the object
1399 * type is one of MONO_CUSTOM_ATTR_*
1402 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1404 MONO_REQ_GC_UNSAFE_MODE;
1406 MonoDynamicTable *table;
1407 MonoReflectionCustomAttr *cattr;
1409 guint32 count, i, token;
1411 char *p = blob_size;
1413 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1416 count = mono_array_length (cattrs);
1417 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1418 table->rows += count;
1419 alloc_table (table, table->rows);
1420 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1421 idx <<= MONO_CUSTOM_ATTR_BITS;
1423 for (i = 0; i < count; ++i) {
1424 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1425 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1426 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1427 type = mono_metadata_token_index (token);
1428 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1429 switch (mono_metadata_token_table (token)) {
1430 case MONO_TABLE_METHOD:
1431 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1433 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1434 * method, not the one returned by mono_image_create_token ().
1436 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1438 case MONO_TABLE_MEMBERREF:
1439 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1442 g_warning ("got wrong token in custom attr");
1445 values [MONO_CUSTOM_ATTR_TYPE] = type;
1447 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1448 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1449 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1450 values += MONO_CUSTOM_ATTR_SIZE;
1456 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1458 MONO_REQ_GC_UNSAFE_MODE;
1460 MonoDynamicTable *table;
1462 guint32 count, i, idx;
1463 MonoReflectionPermissionSet *perm;
1468 count = mono_array_length (permissions);
1469 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1470 table->rows += count;
1471 alloc_table (table, table->rows);
1473 for (i = 0; i < mono_array_length (permissions); ++i) {
1474 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1476 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1478 idx = mono_metadata_token_index (parent_token);
1479 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1480 switch (mono_metadata_token_table (parent_token)) {
1481 case MONO_TABLE_TYPEDEF:
1482 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1484 case MONO_TABLE_METHOD:
1485 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1487 case MONO_TABLE_ASSEMBLY:
1488 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1491 g_assert_not_reached ();
1494 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1495 values [MONO_DECL_SECURITY_PARENT] = idx;
1496 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1503 * Fill in the MethodDef and ParamDef tables for a method.
1504 * This is used for both normal methods and constructors.
1507 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1509 MONO_REQ_GC_UNSAFE_MODE;
1511 MonoDynamicTable *table;
1515 /* room in this table is already allocated */
1516 table = &assembly->tables [MONO_TABLE_METHOD];
1517 *mb->table_idx = table->next_idx ++;
1518 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1519 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1520 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1521 values [MONO_METHOD_FLAGS] = mb->attrs;
1522 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1523 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1524 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1526 table = &assembly->tables [MONO_TABLE_PARAM];
1527 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1529 mono_image_add_decl_security (assembly,
1530 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1533 MonoDynamicTable *mtable;
1536 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1537 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1540 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1541 if (mono_array_get (mb->pinfo, gpointer, i))
1544 table->rows += count;
1545 alloc_table (table, table->rows);
1546 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1547 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1548 MonoReflectionParamBuilder *pb;
1549 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1550 values [MONO_PARAM_FLAGS] = pb->attrs;
1551 values [MONO_PARAM_SEQUENCE] = i;
1552 if (pb->name != NULL) {
1553 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1555 values [MONO_PARAM_NAME] = 0;
1557 values += MONO_PARAM_SIZE;
1558 if (pb->marshal_info) {
1560 alloc_table (mtable, mtable->rows);
1561 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1562 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1563 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1565 pb->table_idx = table->next_idx++;
1566 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1567 guint32 field_type = 0;
1568 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1570 alloc_table (mtable, mtable->rows);
1571 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1572 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1573 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1574 mvalues [MONO_CONSTANT_TYPE] = field_type;
1575 mvalues [MONO_CONSTANT_PADDING] = 0;
1582 #ifndef DISABLE_REFLECTION_EMIT
1584 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1586 MONO_REQ_GC_UNSAFE_MODE;
1588 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1590 rmb->ilgen = mb->ilgen;
1591 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1592 rmb->parameters = mb->parameters;
1593 rmb->generic_params = mb->generic_params;
1594 rmb->generic_container = mb->generic_container;
1595 rmb->opt_types = NULL;
1596 rmb->pinfo = mb->pinfo;
1597 rmb->attrs = mb->attrs;
1598 rmb->iattrs = mb->iattrs;
1599 rmb->call_conv = mb->call_conv;
1600 rmb->code = mb->code;
1601 rmb->type = mb->type;
1602 rmb->name = mb->name;
1603 rmb->table_idx = &mb->table_idx;
1604 rmb->init_locals = mb->init_locals;
1605 rmb->skip_visibility = FALSE;
1606 rmb->return_modreq = mb->return_modreq;
1607 rmb->return_modopt = mb->return_modopt;
1608 rmb->param_modreq = mb->param_modreq;
1609 rmb->param_modopt = mb->param_modopt;
1610 rmb->permissions = mb->permissions;
1611 rmb->mhandle = mb->mhandle;
1616 rmb->charset = mb->charset;
1617 rmb->extra_flags = mb->extra_flags;
1618 rmb->native_cc = mb->native_cc;
1619 rmb->dllentry = mb->dllentry;
1625 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1627 MONO_REQ_GC_UNSAFE_MODE;
1629 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1631 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1633 rmb->ilgen = mb->ilgen;
1634 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1635 rmb->parameters = mb->parameters;
1636 rmb->generic_params = NULL;
1637 rmb->generic_container = NULL;
1638 rmb->opt_types = NULL;
1639 rmb->pinfo = mb->pinfo;
1640 rmb->attrs = mb->attrs;
1641 rmb->iattrs = mb->iattrs;
1642 rmb->call_conv = mb->call_conv;
1644 rmb->type = mb->type;
1645 rmb->name = mono_string_new (mono_domain_get (), name);
1646 rmb->table_idx = &mb->table_idx;
1647 rmb->init_locals = mb->init_locals;
1648 rmb->skip_visibility = FALSE;
1649 rmb->return_modreq = NULL;
1650 rmb->return_modopt = NULL;
1651 rmb->param_modreq = mb->param_modreq;
1652 rmb->param_modopt = mb->param_modopt;
1653 rmb->permissions = mb->permissions;
1654 rmb->mhandle = mb->mhandle;
1660 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1662 MONO_REQ_GC_UNSAFE_MODE;
1664 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1666 rmb->ilgen = mb->ilgen;
1667 rmb->rtype = mb->rtype;
1668 rmb->parameters = mb->parameters;
1669 rmb->generic_params = NULL;
1670 rmb->generic_container = NULL;
1671 rmb->opt_types = NULL;
1673 rmb->attrs = mb->attrs;
1675 rmb->call_conv = mb->call_conv;
1677 rmb->type = (MonoObject *) mb->owner;
1678 rmb->name = mb->name;
1679 rmb->table_idx = NULL;
1680 rmb->init_locals = mb->init_locals;
1681 rmb->skip_visibility = mb->skip_visibility;
1682 rmb->return_modreq = NULL;
1683 rmb->return_modopt = NULL;
1684 rmb->param_modreq = NULL;
1685 rmb->param_modopt = NULL;
1686 rmb->permissions = NULL;
1687 rmb->mhandle = mb->mhandle;
1694 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1696 MONO_REQ_GC_UNSAFE_MODE;
1698 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1699 MonoDynamicTable *table;
1702 MonoReflectionMethod *m;
1705 if (!mb->override_methods)
1708 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1709 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1711 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1713 alloc_table (table, table->rows);
1714 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1715 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1716 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1718 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1719 switch (mono_metadata_token_table (tok)) {
1720 case MONO_TABLE_MEMBERREF:
1721 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1723 case MONO_TABLE_METHOD:
1724 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1727 g_assert_not_reached ();
1729 values [MONO_METHODIMPL_DECLARATION] = tok;
1733 #ifndef DISABLE_REFLECTION_EMIT
1735 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1737 MONO_REQ_GC_UNSAFE_MODE;
1739 MonoDynamicTable *table;
1741 ReflectionMethodBuilder rmb;
1744 reflection_methodbuilder_from_method_builder (&rmb, mb);
1746 mono_image_basic_method (&rmb, assembly);
1747 mb->table_idx = *rmb.table_idx;
1749 if (mb->dll) { /* It's a P/Invoke method */
1751 /* map CharSet values to on-disk values */
1752 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1753 int extra_flags = mb->extra_flags;
1754 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1759 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1760 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1762 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1764 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1765 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1766 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1767 table = &assembly->tables [MONO_TABLE_MODULEREF];
1769 alloc_table (table, table->rows);
1770 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1771 values [MONO_IMPLMAP_SCOPE] = table->rows;
1775 if (mb->generic_params) {
1776 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1777 table->rows += mono_array_length (mb->generic_params);
1778 alloc_table (table, table->rows);
1779 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1780 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1782 mono_image_get_generic_param_info (
1783 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1790 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1792 MONO_REQ_GC_UNSAFE_MODE;
1794 ReflectionMethodBuilder rmb;
1796 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1798 mono_image_basic_method (&rmb, assembly);
1799 mb->table_idx = *rmb.table_idx;
1804 type_get_fully_qualified_name (MonoType *type)
1806 MONO_REQ_GC_NEUTRAL_MODE;
1808 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1812 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1814 MONO_REQ_GC_UNSAFE_MODE;
1819 klass = mono_class_from_mono_type (type);
1821 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1822 ta = klass->image->assembly;
1823 if (assembly_is_dynamic (ta) || (ta == ass)) {
1824 if (klass->generic_class || klass->generic_container)
1825 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1826 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1828 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1831 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1834 #ifndef DISABLE_REFLECTION_EMIT
1835 /*field_image is the image to which the eventual custom mods have been encoded against*/
1837 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1839 MONO_REQ_GC_NEUTRAL_MODE;
1842 guint32 idx, i, token;
1844 if (!assembly->save)
1847 sigbuffer_init (&buf, 32);
1849 sigbuffer_add_value (&buf, 0x06);
1850 /* encode custom attributes before the type */
1851 if (type->num_mods) {
1852 for (i = 0; i < type->num_mods; ++i) {
1855 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1856 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1858 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1860 token = type->modifiers [i].token;
1863 if (type->modifiers [i].required)
1864 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1866 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1868 sigbuffer_add_value (&buf, token);
1871 encode_type (assembly, type, &buf);
1872 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1873 sigbuffer_free (&buf);
1879 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1881 MONO_REQ_GC_UNSAFE_MODE;
1885 guint32 typespec = 0;
1889 init_type_builder_generics (fb->type);
1891 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1892 class = mono_class_from_mono_type (type);
1894 sigbuffer_init (&buf, 32);
1896 sigbuffer_add_value (&buf, 0x06);
1897 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1898 /* encode custom attributes before the type */
1900 if (class->generic_container)
1901 typespec = create_typespec (assembly, type);
1904 MonoGenericClass *gclass;
1905 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1906 encode_generic_class (assembly, gclass, &buf);
1908 encode_type (assembly, type, &buf);
1910 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1911 sigbuffer_free (&buf);
1916 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1918 MONO_REQ_GC_UNSAFE_MODE;
1920 char blob_size [64];
1921 char *b = blob_size;
1924 guint32 idx = 0, len = 0, dummy = 0;
1926 buf = g_malloc (64);
1928 *ret_type = MONO_TYPE_CLASS;
1930 box_val = (char*)&dummy;
1932 box_val = ((char*)val) + sizeof (MonoObject);
1933 *ret_type = val->vtable->klass->byval_arg.type;
1936 switch (*ret_type) {
1937 case MONO_TYPE_BOOLEAN:
1942 case MONO_TYPE_CHAR:
1959 case MONO_TYPE_VALUETYPE: {
1960 MonoClass *klass = val->vtable->klass;
1962 if (klass->enumtype) {
1963 *ret_type = mono_class_enum_basetype (klass)->type;
1965 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1968 g_error ("we can't encode valuetypes, we should have never reached this line");
1971 case MONO_TYPE_CLASS:
1973 case MONO_TYPE_STRING: {
1974 MonoString *str = (MonoString*)val;
1975 /* there is no signature */
1976 len = str->length * 2;
1977 mono_metadata_encode_value (len, b, &b);
1978 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1980 char *swapped = g_malloc (2 * mono_string_length (str));
1981 const char *p = (const char*)mono_string_chars (str);
1983 swap_with_size (swapped, p, 2, mono_string_length (str));
1984 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1988 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1994 case MONO_TYPE_GENERICINST:
1995 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1998 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2001 /* there is no signature */
2002 mono_metadata_encode_value (len, b, &b);
2003 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2004 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2005 swap_with_size (blob_size, box_val, len, 1);
2006 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2008 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2016 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2018 MONO_REQ_GC_UNSAFE_MODE;
2024 sigbuffer_init (&buf, 32);
2026 sigbuffer_add_value (&buf, minfo->type);
2028 switch (minfo->type) {
2029 case MONO_NATIVE_BYVALTSTR:
2030 case MONO_NATIVE_BYVALARRAY:
2031 sigbuffer_add_value (&buf, minfo->count);
2033 case MONO_NATIVE_LPARRAY:
2034 if (minfo->eltype || minfo->has_size) {
2035 sigbuffer_add_value (&buf, minfo->eltype);
2036 if (minfo->has_size) {
2037 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2038 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2040 /* LAMESPEC: ElemMult is undocumented */
2041 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2045 case MONO_NATIVE_SAFEARRAY:
2047 sigbuffer_add_value (&buf, minfo->eltype);
2049 case MONO_NATIVE_CUSTOM:
2051 str = mono_string_to_utf8 (minfo->guid);
2053 sigbuffer_add_value (&buf, len);
2054 sigbuffer_add_mem (&buf, str, len);
2057 sigbuffer_add_value (&buf, 0);
2059 /* native type name */
2060 sigbuffer_add_value (&buf, 0);
2061 /* custom marshaler type name */
2062 if (minfo->marshaltype || minfo->marshaltyperef) {
2063 if (minfo->marshaltyperef)
2064 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2066 str = mono_string_to_utf8 (minfo->marshaltype);
2068 sigbuffer_add_value (&buf, len);
2069 sigbuffer_add_mem (&buf, str, len);
2072 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2073 sigbuffer_add_value (&buf, 0);
2075 if (minfo->mcookie) {
2076 str = mono_string_to_utf8 (minfo->mcookie);
2078 sigbuffer_add_value (&buf, len);
2079 sigbuffer_add_mem (&buf, str, len);
2082 sigbuffer_add_value (&buf, 0);
2088 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089 sigbuffer_free (&buf);
2094 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2096 MONO_REQ_GC_UNSAFE_MODE;
2098 MonoDynamicTable *table;
2101 /* maybe this fixup should be done in the C# code */
2102 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2103 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2104 table = &assembly->tables [MONO_TABLE_FIELD];
2105 fb->table_idx = table->next_idx ++;
2106 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2107 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2108 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2109 values [MONO_FIELD_FLAGS] = fb->attrs;
2110 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2112 if (fb->offset != -1) {
2113 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2115 alloc_table (table, table->rows);
2116 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2117 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2118 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2120 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2121 guint32 field_type = 0;
2122 table = &assembly->tables [MONO_TABLE_CONSTANT];
2124 alloc_table (table, table->rows);
2125 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2126 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2127 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2128 values [MONO_CONSTANT_TYPE] = field_type;
2129 values [MONO_CONSTANT_PADDING] = 0;
2131 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2133 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2135 alloc_table (table, table->rows);
2136 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2137 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2139 * We store it in the code section because it's simpler for now.
2142 if (mono_array_length (fb->rva_data) >= 10)
2143 stream_data_align (&assembly->code);
2144 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2146 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2147 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2149 if (fb->marshal_info) {
2150 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2152 alloc_table (table, table->rows);
2153 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2154 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2155 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2160 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2162 MONO_REQ_GC_UNSAFE_MODE;
2165 guint32 nparams = 0;
2166 MonoReflectionMethodBuilder *mb = fb->get_method;
2167 MonoReflectionMethodBuilder *smb = fb->set_method;
2170 if (mb && mb->parameters)
2171 nparams = mono_array_length (mb->parameters);
2172 if (!mb && smb && smb->parameters)
2173 nparams = mono_array_length (smb->parameters) - 1;
2174 sigbuffer_init (&buf, 32);
2175 if (fb->call_conv & 0x20)
2176 sigbuffer_add_byte (&buf, 0x28);
2178 sigbuffer_add_byte (&buf, 0x08);
2179 sigbuffer_add_value (&buf, nparams);
2181 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2182 for (i = 0; i < nparams; ++i) {
2183 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2184 encode_reflection_type (assembly, pt, &buf);
2186 } else if (smb && smb->parameters) {
2187 /* the property type is the last param */
2188 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2189 for (i = 0; i < nparams; ++i) {
2190 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2191 encode_reflection_type (assembly, pt, &buf);
2194 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2197 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2198 sigbuffer_free (&buf);
2203 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2205 MONO_REQ_GC_UNSAFE_MODE;
2207 MonoDynamicTable *table;
2209 guint num_methods = 0;
2213 * we need to set things in the following tables:
2214 * PROPERTYMAP (info already filled in _get_type_info ())
2215 * PROPERTY (rows already preallocated in _get_type_info ())
2216 * METHOD (method info already done with the generic method code)
2220 table = &assembly->tables [MONO_TABLE_PROPERTY];
2221 pb->table_idx = table->next_idx ++;
2222 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2223 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2224 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2225 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2227 /* FIXME: we still don't handle 'other' methods */
2228 if (pb->get_method) num_methods ++;
2229 if (pb->set_method) num_methods ++;
2231 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2232 table->rows += num_methods;
2233 alloc_table (table, table->rows);
2235 if (pb->get_method) {
2236 semaidx = table->next_idx ++;
2237 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2238 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2239 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2240 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2242 if (pb->set_method) {
2243 semaidx = table->next_idx ++;
2244 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2245 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2246 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2247 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2249 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2250 guint32 field_type = 0;
2251 table = &assembly->tables [MONO_TABLE_CONSTANT];
2253 alloc_table (table, table->rows);
2254 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2255 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2256 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2257 values [MONO_CONSTANT_TYPE] = field_type;
2258 values [MONO_CONSTANT_PADDING] = 0;
2263 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2265 MONO_REQ_GC_UNSAFE_MODE;
2267 MonoDynamicTable *table;
2269 guint num_methods = 0;
2273 * we need to set things in the following tables:
2274 * EVENTMAP (info already filled in _get_type_info ())
2275 * EVENT (rows already preallocated in _get_type_info ())
2276 * METHOD (method info already done with the generic method code)
2279 table = &assembly->tables [MONO_TABLE_EVENT];
2280 eb->table_idx = table->next_idx ++;
2281 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2282 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2283 values [MONO_EVENT_FLAGS] = eb->attrs;
2284 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2287 * FIXME: we still don't handle 'other' methods
2289 if (eb->add_method) num_methods ++;
2290 if (eb->remove_method) num_methods ++;
2291 if (eb->raise_method) num_methods ++;
2293 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2294 table->rows += num_methods;
2295 alloc_table (table, table->rows);
2297 if (eb->add_method) {
2298 semaidx = table->next_idx ++;
2299 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2300 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2301 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2302 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2304 if (eb->remove_method) {
2305 semaidx = table->next_idx ++;
2306 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2307 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2308 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2309 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2311 if (eb->raise_method) {
2312 semaidx = table->next_idx ++;
2313 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2314 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2315 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2316 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2321 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2323 MONO_REQ_GC_UNSAFE_MODE;
2325 MonoDynamicTable *table;
2326 guint32 num_constraints, i;
2330 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2331 num_constraints = gparam->iface_constraints ?
2332 mono_array_length (gparam->iface_constraints) : 0;
2333 table->rows += num_constraints;
2334 if (gparam->base_type)
2336 alloc_table (table, table->rows);
2338 if (gparam->base_type) {
2339 table_idx = table->next_idx ++;
2340 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2342 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2343 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2344 assembly, mono_reflection_type_get_handle (gparam->base_type));
2347 for (i = 0; i < num_constraints; i++) {
2348 MonoReflectionType *constraint = mono_array_get (
2349 gparam->iface_constraints, gpointer, i);
2351 table_idx = table->next_idx ++;
2352 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2354 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2355 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2356 assembly, mono_reflection_type_get_handle (constraint));
2361 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2363 MONO_REQ_GC_UNSAFE_MODE;
2365 GenericParamTableEntry *entry;
2368 * The GenericParam table must be sorted according to the `owner' field.
2369 * We need to do this sorting prior to writing the GenericParamConstraint
2370 * table, since we have to use the final GenericParam table indices there
2371 * and they must also be sorted.
2374 entry = g_new0 (GenericParamTableEntry, 1);
2375 entry->owner = owner;
2376 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2377 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2378 entry->gparam = gparam;
2380 g_ptr_array_add (assembly->gen_params, entry);
2384 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2386 MONO_REQ_GC_UNSAFE_MODE;
2388 MonoDynamicTable *table;
2389 MonoGenericParam *param;
2393 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2394 table_idx = table->next_idx ++;
2395 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2397 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2399 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2400 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2401 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2402 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2404 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2406 encode_constraints (entry->gparam, table_idx, assembly);
2410 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2412 MONO_REQ_GC_UNSAFE_MODE;
2414 MonoDynamicTable *table;
2417 guint32 cols [MONO_ASSEMBLY_SIZE];
2421 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2424 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2425 table = &assembly->tables [MONO_TABLE_MODULEREF];
2426 token = table->next_idx ++;
2428 alloc_table (table, table->rows);
2429 values = table->values + token * MONO_MODULEREF_SIZE;
2430 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2432 token <<= MONO_RESOLUTION_SCOPE_BITS;
2433 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2434 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2439 if (assembly_is_dynamic (image->assembly))
2441 memset (cols, 0, sizeof (cols));
2443 /* image->assembly->image is the manifest module */
2444 image = image->assembly->image;
2445 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2448 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2449 token = table->next_idx ++;
2451 alloc_table (table, table->rows);
2452 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2453 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2454 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2455 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2456 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2457 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2458 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2459 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2460 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2462 if (strcmp ("", image->assembly->aname.culture)) {
2463 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2464 image->assembly->aname.culture);
2467 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2468 guchar pubtoken [9];
2470 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2471 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2473 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2475 token <<= MONO_RESOLUTION_SCOPE_BITS;
2476 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2477 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2482 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2484 MONO_REQ_GC_NEUTRAL_MODE;
2486 MonoDynamicTable *table;
2491 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2494 sigbuffer_init (&buf, 32);
2495 switch (type->type) {
2496 case MONO_TYPE_FNPTR:
2498 case MONO_TYPE_SZARRAY:
2499 case MONO_TYPE_ARRAY:
2501 case MONO_TYPE_MVAR:
2502 case MONO_TYPE_GENERICINST:
2503 encode_type (assembly, type, &buf);
2505 case MONO_TYPE_CLASS:
2506 case MONO_TYPE_VALUETYPE: {
2507 MonoClass *k = mono_class_from_mono_type (type);
2508 if (!k || !k->generic_container) {
2509 sigbuffer_free (&buf);
2512 encode_type (assembly, type, &buf);
2516 sigbuffer_free (&buf);
2520 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2521 if (assembly->save) {
2522 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2523 alloc_table (table, table->rows + 1);
2524 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2525 values [MONO_TYPESPEC_SIGNATURE] = token;
2527 sigbuffer_free (&buf);
2529 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2530 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2536 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2538 MONO_REQ_GC_UNSAFE_MODE;
2540 MonoDynamicTable *table;
2542 guint32 token, scope, enclosing;
2545 /* if the type requires a typespec, we must try that first*/
2546 if (try_typespec && (token = create_typespec (assembly, type)))
2548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2551 klass = mono_class_from_mono_type (type);
2553 klass = mono_class_from_mono_type (type);
2556 * If it's in the same module and not a generic type parameter:
2558 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2559 (type->type != MONO_TYPE_MVAR)) {
2560 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2561 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2562 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2566 if (klass->nested_in) {
2567 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2568 /* get the typeref idx of the enclosing type */
2569 enclosing >>= MONO_TYPEDEFORREF_BITS;
2570 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2572 scope = resolution_scope_from_image (assembly, klass->image);
2574 table = &assembly->tables [MONO_TABLE_TYPEREF];
2575 if (assembly->save) {
2576 alloc_table (table, table->rows + 1);
2577 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2578 values [MONO_TYPEREF_SCOPE] = scope;
2579 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2580 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2582 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2583 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2585 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2590 * Despite the name, we handle also TypeSpec (with the above helper).
2593 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2595 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2598 #ifndef DISABLE_REFLECTION_EMIT
2600 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2602 MONO_REQ_GC_NEUTRAL_MODE;
2604 MonoDynamicTable *table;
2606 guint32 token, pclass;
2608 switch (parent & MONO_TYPEDEFORREF_MASK) {
2609 case MONO_TYPEDEFORREF_TYPEREF:
2610 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2612 case MONO_TYPEDEFORREF_TYPESPEC:
2613 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2615 case MONO_TYPEDEFORREF_TYPEDEF:
2616 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2619 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2622 /* extract the index */
2623 parent >>= MONO_TYPEDEFORREF_BITS;
2625 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2627 if (assembly->save) {
2628 alloc_table (table, table->rows + 1);
2629 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2630 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2631 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2632 values [MONO_MEMBERREF_SIGNATURE] = sig;
2635 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2642 * Insert a memberef row into the metadata: the token that point to the memberref
2643 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2644 * mono_image_get_fieldref_token()).
2645 * The sig param is an index to an already built signature.
2648 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2650 MONO_REQ_GC_NEUTRAL_MODE;
2652 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2653 return mono_image_add_memberef_row (assembly, parent, name, sig);
2658 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2660 MONO_REQ_GC_NEUTRAL_MODE;
2663 MonoMethodSignature *sig;
2665 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2667 if (create_typespec) {
2668 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2673 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2674 if (token && !create_typespec)
2677 g_assert (!method->is_inflated);
2680 * A methodref signature can't contain an unmanaged calling convention.
2682 sig = mono_metadata_signature_dup (mono_method_signature (method));
2683 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2684 sig->call_convention = MONO_CALL_DEFAULT;
2685 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2686 method->name, method_encode_signature (assembly, sig));
2688 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2691 if (create_typespec) {
2692 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2693 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2694 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2696 if (assembly->save) {
2699 alloc_table (table, table->rows + 1);
2700 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2701 values [MONO_METHODSPEC_METHOD] = token;
2702 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2705 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2707 /*methodspec and memberef tokens are diferent, */
2708 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2715 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2717 guint32 token, parent, sig;
2718 ReflectionMethodBuilder rmb;
2720 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2722 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2726 name = mono_string_to_utf8 (method->name);
2727 reflection_methodbuilder_from_method_builder (&rmb, method);
2730 * A methodref signature can't contain an unmanaged calling convention.
2731 * Since some flags are encoded as part of call_conv, we need to check against it.
2733 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2734 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2736 sig = method_builder_encode_signature (assembly, &rmb);
2738 if (tb->generic_params)
2739 parent = create_generic_typespec (assembly, tb);
2741 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2743 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2746 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2751 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2752 const gchar *name, guint32 sig)
2754 MonoDynamicTable *table;
2758 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2760 if (assembly->save) {
2761 alloc_table (table, table->rows + 1);
2762 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2763 values [MONO_MEMBERREF_CLASS] = original;
2764 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2765 values [MONO_MEMBERREF_SIGNATURE] = sig;
2768 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2775 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2779 guint32 nparams = mono_array_length (mb->generic_params);
2782 if (!assembly->save)
2785 sigbuffer_init (&buf, 32);
2787 sigbuffer_add_value (&buf, 0xa);
2788 sigbuffer_add_value (&buf, nparams);
2790 for (i = 0; i < nparams; i++) {
2791 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2792 sigbuffer_add_value (&buf, i);
2795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2796 sigbuffer_free (&buf);
2801 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2803 MonoDynamicTable *table;
2805 guint32 token, mtoken = 0;
2807 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2811 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2813 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2814 switch (mono_metadata_token_table (mtoken)) {
2815 case MONO_TABLE_MEMBERREF:
2816 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2818 case MONO_TABLE_METHOD:
2819 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2822 g_assert_not_reached ();
2825 if (assembly->save) {
2826 alloc_table (table, table->rows + 1);
2827 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2828 values [MONO_METHODSPEC_METHOD] = mtoken;
2829 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2832 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2835 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2840 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2844 if (mb->generic_params && create_methodspec)
2845 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2847 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2851 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2852 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2857 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2859 guint32 token, parent, sig;
2860 ReflectionMethodBuilder rmb;
2862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2864 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2868 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2870 if (tb->generic_params)
2871 parent = create_generic_typespec (assembly, tb);
2873 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2875 name = mono_string_to_utf8 (rmb.name);
2876 sig = method_builder_encode_signature (assembly, &rmb);
2878 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2881 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2887 is_field_on_inst (MonoClassField *field)
2889 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2893 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2896 get_field_on_inst_generic_type (MonoClassField *field)
2898 MonoClass *class, *gtd;
2899 MonoDynamicGenericClass *dgclass;
2902 g_assert (is_field_on_inst (field));
2904 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2906 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2907 field_index = field - dgclass->fields;
2908 return dgclass->field_generic_types [field_index];
2911 class = field->parent;
2912 gtd = class->generic_class->container_class;
2914 if (field >= class->fields && field - class->fields < class->field.count) {
2915 field_index = field - class->fields;
2916 return gtd->fields [field_index].type;
2919 g_assert_not_reached ();
2923 #ifndef DISABLE_REFLECTION_EMIT
2925 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2931 g_assert (field->parent);
2933 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2937 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2938 int index = field - field->parent->fields;
2939 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2941 if (is_field_on_inst (field))
2942 type = get_field_on_inst_generic_type (field);
2944 type = mono_field_get_type (field);
2946 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2947 mono_field_get_name (field),
2948 fieldref_encode_signature (assembly, field->parent->image, type));
2949 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2954 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2958 MonoGenericClass *gclass;
2962 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2965 if (is_sre_field_builder (mono_object_class (f->fb))) {
2966 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2967 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2968 klass = mono_class_from_mono_type (type);
2969 gclass = type->data.generic_class;
2970 g_assert (gclass->is_dynamic);
2972 name = mono_string_to_utf8 (fb->name);
2973 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2974 field_encode_signature (assembly, fb));
2976 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2978 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2980 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2981 klass = mono_class_from_mono_type (type);
2983 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2984 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2986 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2987 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2990 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2995 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2999 MonoGenericClass *gclass;
3002 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3004 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3008 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3009 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3010 ReflectionMethodBuilder rmb;
3013 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3014 klass = mono_class_from_mono_type (type);
3016 gclass = type->data.generic_class;
3017 g_assert (gclass->is_dynamic);
3019 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3021 name = mono_string_to_utf8 (rmb.name);
3023 sig = method_builder_encode_signature (assembly, &rmb);
3025 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3027 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3028 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3030 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3031 klass = mono_class_from_mono_type (type);
3033 sig = method_encode_signature (assembly, mono_method_signature (mm));
3034 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3036 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3037 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3041 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3046 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3050 MonoGenericContext tmp_context;
3051 MonoType **type_argv;
3052 MonoGenericInst *ginst;
3053 MonoMethod *method, *inflated;
3056 init_type_builder_generics ((MonoObject*)m->inst);
3058 method = inflate_method (m->inst, (MonoObject*)m->mb);
3060 klass = method->klass;
3062 if (m->method_args == NULL)
3065 if (method->is_inflated)
3066 method = ((MonoMethodInflated *) method)->declaring;
3068 count = mono_array_length (m->method_args);
3070 type_argv = g_new0 (MonoType *, count);
3071 for (i = 0; i < count; i++) {
3072 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3073 type_argv [i] = mono_reflection_type_get_handle (garg);
3075 ginst = mono_metadata_get_generic_inst (count, type_argv);
3078 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3079 tmp_context.method_inst = ginst;
3081 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3082 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3087 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3089 guint32 sig, token = 0;
3093 if (m->method_args) {
3094 MonoMethod *inflated;
3096 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3097 if (create_methodspec)
3098 token = mono_image_get_methodspec_token (assembly, inflated);
3100 token = mono_image_get_inflated_method_token (assembly, inflated);
3104 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3108 if (is_sre_method_builder (mono_object_class (m->mb))) {
3109 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3110 MonoGenericClass *gclass;
3111 ReflectionMethodBuilder rmb;
3114 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3115 klass = mono_class_from_mono_type (type);
3116 gclass = type->data.generic_class;
3117 g_assert (gclass->is_dynamic);
3119 reflection_methodbuilder_from_method_builder (&rmb, mb);
3121 name = mono_string_to_utf8 (rmb.name);
3123 sig = method_builder_encode_signature (assembly, &rmb);
3125 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3127 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3128 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3130 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3131 klass = mono_class_from_mono_type (type);
3133 sig = method_encode_signature (assembly, mono_method_signature (mm));
3134 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3136 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3137 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3140 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3145 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3149 guint32 nparams = context->method_inst->type_argc;
3152 if (!assembly->save)
3155 sigbuffer_init (&buf, 32);
3157 * FIXME: vararg, explicit_this, differenc call_conv values...
3159 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3160 sigbuffer_add_value (&buf, nparams);
3162 for (i = 0; i < nparams; i++)
3163 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3165 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3166 sigbuffer_free (&buf);
3171 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3173 MonoDynamicTable *table;
3175 guint32 token, mtoken = 0, sig;
3176 MonoMethodInflated *imethod;
3177 MonoMethod *declaring;
3179 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3181 g_assert (method->is_inflated);
3182 imethod = (MonoMethodInflated *) method;
3183 declaring = imethod->declaring;
3185 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3186 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3188 if (!mono_method_signature (declaring)->generic_param_count)
3191 switch (mono_metadata_token_table (mtoken)) {
3192 case MONO_TABLE_MEMBERREF:
3193 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3195 case MONO_TABLE_METHOD:
3196 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3199 g_assert_not_reached ();
3202 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3204 if (assembly->save) {
3205 alloc_table (table, table->rows + 1);
3206 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3207 values [MONO_METHODSPEC_METHOD] = mtoken;
3208 values [MONO_METHODSPEC_SIGNATURE] = sig;
3211 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3218 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3220 MonoMethodInflated *imethod;
3223 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3227 g_assert (method->is_inflated);
3228 imethod = (MonoMethodInflated *) method;
3230 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3231 token = method_encode_methodspec (assembly, method);
3233 guint32 sig = method_encode_signature (
3234 assembly, mono_method_signature (imethod->declaring));
3235 token = mono_image_get_memberref_token (
3236 assembly, &method->klass->byval_arg, method->name, sig);
3239 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3244 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3246 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3249 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3250 token = mono_image_get_memberref_token (
3251 assembly, &m->klass->byval_arg, m->name, sig);
3257 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3259 MonoDynamicTable *table;
3268 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3269 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3270 * Because of this, we must not insert it into the `typeref' hash table.
3272 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3273 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3277 sigbuffer_init (&buf, 32);
3279 g_assert (tb->generic_params);
3280 klass = mono_class_from_mono_type (type);
3282 if (tb->generic_container)
3283 mono_reflection_create_generic_class (tb);
3285 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3286 g_assert (klass->generic_container);
3287 sigbuffer_add_value (&buf, klass->byval_arg.type);
3288 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3290 count = mono_array_length (tb->generic_params);
3291 sigbuffer_add_value (&buf, count);
3292 for (i = 0; i < count; i++) {
3293 MonoReflectionGenericParam *gparam;
3295 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3297 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3300 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3302 if (assembly->save) {
3303 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3304 alloc_table (table, table->rows + 1);
3305 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3306 values [MONO_TYPESPEC_SIGNATURE] = token;
3308 sigbuffer_free (&buf);
3310 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3311 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3317 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3320 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3322 int i, count, len, pos;
3327 count += mono_array_length (modreq);
3329 count += mono_array_length (modopt);
3332 return mono_metadata_type_dup (NULL, type);
3334 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3336 memcpy (t, type, MONO_SIZEOF_TYPE);
3338 t->num_mods = count;
3341 for (i = 0; i < mono_array_length (modreq); ++i) {
3342 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3343 t->modifiers [pos].required = 1;
3344 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3349 for (i = 0; i < mono_array_length (modopt); ++i) {
3350 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3351 t->modifiers [pos].required = 0;
3352 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3361 init_type_builder_generics (MonoObject *type)
3363 MonoReflectionTypeBuilder *tb;
3365 if (!is_sre_type_builder(mono_object_class (type)))
3367 tb = (MonoReflectionTypeBuilder *)type;
3369 if (tb && tb->generic_container)
3370 mono_reflection_create_generic_class (tb);
3374 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3376 MonoDynamicTable *table;
3377 MonoType *custom = NULL, *type;
3379 guint32 token, pclass, parent, sig;
3382 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3386 /* FIXME: is this call necessary? */
3387 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3388 name = mono_string_to_utf8 (fb->name);
3390 /*FIXME this is one more layer of ugliness due how types are created.*/
3391 init_type_builder_generics (fb->type);
3393 /* fb->type does not include the custom modifiers */
3394 /* FIXME: We should do this in one place when a fieldbuilder is created */
3395 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3396 if (fb->modreq || fb->modopt)
3397 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3399 sig = fieldref_encode_signature (assembly, NULL, type);
3402 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3403 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3405 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3406 parent >>= MONO_TYPEDEFORREF_BITS;
3408 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3410 if (assembly->save) {
3411 alloc_table (table, table->rows + 1);
3412 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3413 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3414 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3415 values [MONO_MEMBERREF_SIGNATURE] = sig;
3418 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3420 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3426 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3432 if (!assembly->save)
3435 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3436 g_assert (helper->type == 2);
3438 if (helper->arguments)
3439 nargs = mono_array_length (helper->arguments);
3443 sigbuffer_init (&buf, 32);
3445 /* Encode calling convention */
3446 /* Change Any to Standard */
3447 if ((helper->call_conv & 0x03) == 0x03)
3448 helper->call_conv = 0x01;
3449 /* explicit_this implies has_this */
3450 if (helper->call_conv & 0x40)
3451 helper->call_conv &= 0x20;
3453 if (helper->call_conv == 0) { /* Unmanaged */
3454 idx = helper->unmanaged_call_conv - 1;
3457 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3458 if (helper->call_conv & 0x02) /* varargs */
3462 sigbuffer_add_byte (&buf, idx);
3463 sigbuffer_add_value (&buf, nargs);
3464 encode_reflection_type (assembly, helper->return_type, &buf);
3465 for (i = 0; i < nargs; ++i) {
3466 MonoArray *modreqs = NULL;
3467 MonoArray *modopts = NULL;
3468 MonoReflectionType *pt;
3470 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3471 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3472 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3473 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3475 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3476 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3477 encode_reflection_type (assembly, pt, &buf);
3479 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3480 sigbuffer_free (&buf);
3486 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3489 MonoDynamicTable *table;
3492 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3493 idx = table->next_idx ++;
3495 alloc_table (table, table->rows);
3496 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3498 values [MONO_STAND_ALONE_SIGNATURE] =
3499 mono_reflection_encode_sighelper (assembly, helper);
3505 reflection_cc_to_file (int call_conv) {
3506 switch (call_conv & 0x3) {
3508 case 1: return MONO_CALL_DEFAULT;
3509 case 2: return MONO_CALL_VARARG;
3511 g_assert_not_reached ();
3515 #endif /* !DISABLE_REFLECTION_EMIT */
3519 MonoMethodSignature *sig;
3524 #ifndef DISABLE_REFLECTION_EMIT
3526 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3531 MonoMethodSignature *sig;
3535 name = mono_string_to_utf8 (m->name);
3536 nparams = mono_array_length (m->parameters);
3537 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3539 sig->sentinelpos = -1;
3540 sig->call_convention = reflection_cc_to_file (m->call_conv);
3541 sig->param_count = nparams;
3542 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3543 mtype = mono_reflection_type_get_handle (m->parent);
3544 for (i = 0; i < nparams; ++i)
3545 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3547 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3549 if (strcmp (name, am->name) == 0 &&
3550 mono_metadata_type_equal (am->parent, mtype) &&
3551 mono_metadata_signature_equal (am->sig, sig)) {
3554 m->table_idx = am->token & 0xffffff;
3558 am = g_new0 (ArrayMethod, 1);
3562 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3563 method_encode_signature (assembly, sig));
3564 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3565 m->table_idx = am->token & 0xffffff;
3570 * Insert into the metadata tables all the info about the TypeBuilder tb.
3571 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3574 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3576 MonoDynamicTable *table;
3578 int i, is_object = 0, is_system = 0;
3581 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3582 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3583 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3584 n = mono_string_to_utf8 (tb->name);
3585 if (strcmp (n, "Object") == 0)
3587 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3589 n = mono_string_to_utf8 (tb->nspace);
3590 if (strcmp (n, "System") == 0)
3592 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3594 if (tb->parent && !(is_system && is_object) &&
3595 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3596 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3598 values [MONO_TYPEDEF_EXTENDS] = 0;
3600 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3601 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3604 * if we have explicitlayout or sequentiallayouts, output data in the
3605 * ClassLayout table.
3607 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3608 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3609 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3611 alloc_table (table, table->rows);
3612 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3613 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3614 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3615 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3618 /* handle interfaces */
3619 if (tb->interfaces) {
3620 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3622 table->rows += mono_array_length (tb->interfaces);
3623 alloc_table (table, table->rows);
3624 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3625 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3626 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3627 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3628 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3629 values += MONO_INTERFACEIMPL_SIZE;
3635 table = &assembly->tables [MONO_TABLE_FIELD];
3636 table->rows += tb->num_fields;
3637 alloc_table (table, table->rows);
3638 for (i = 0; i < tb->num_fields; ++i)
3639 mono_image_get_field_info (
3640 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3643 /* handle constructors */
3645 table = &assembly->tables [MONO_TABLE_METHOD];
3646 table->rows += mono_array_length (tb->ctors);
3647 alloc_table (table, table->rows);
3648 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3649 mono_image_get_ctor_info (domain,
3650 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3653 /* handle methods */
3655 table = &assembly->tables [MONO_TABLE_METHOD];
3656 table->rows += tb->num_methods;
3657 alloc_table (table, table->rows);
3658 for (i = 0; i < tb->num_methods; ++i)
3659 mono_image_get_method_info (
3660 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3663 /* Do the same with properties etc.. */
3664 if (tb->events && mono_array_length (tb->events)) {
3665 table = &assembly->tables [MONO_TABLE_EVENT];
3666 table->rows += mono_array_length (tb->events);
3667 alloc_table (table, table->rows);
3668 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3670 alloc_table (table, table->rows);
3671 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3672 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3673 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3674 for (i = 0; i < mono_array_length (tb->events); ++i)
3675 mono_image_get_event_info (
3676 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3678 if (tb->properties && mono_array_length (tb->properties)) {
3679 table = &assembly->tables [MONO_TABLE_PROPERTY];
3680 table->rows += mono_array_length (tb->properties);
3681 alloc_table (table, table->rows);
3682 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3684 alloc_table (table, table->rows);
3685 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3686 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3687 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3688 for (i = 0; i < mono_array_length (tb->properties); ++i)
3689 mono_image_get_property_info (
3690 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3693 /* handle generic parameters */
3694 if (tb->generic_params) {
3695 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3696 table->rows += mono_array_length (tb->generic_params);
3697 alloc_table (table, table->rows);
3698 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3699 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3701 mono_image_get_generic_param_info (
3702 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3706 mono_image_add_decl_security (assembly,
3707 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3710 MonoDynamicTable *ntable;
3712 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3713 ntable->rows += mono_array_length (tb->subtypes);
3714 alloc_table (ntable, ntable->rows);
3715 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3717 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3718 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3720 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3721 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3722 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3723 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3724 mono_string_to_utf8 (tb->name), tb->table_idx,
3725 ntable->next_idx, ntable->rows);*/
3726 values += MONO_NESTED_CLASS_SIZE;
3734 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3738 mono_ptr_array_append (*types, type);
3740 if (!type->subtypes)
3743 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3744 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3745 collect_types (types, subtype);
3750 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3752 if ((*type1)->table_idx < (*type2)->table_idx)
3755 if ((*type1)->table_idx > (*type2)->table_idx)
3762 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3767 for (i = 0; i < mono_array_length (pinfo); ++i) {
3768 MonoReflectionParamBuilder *pb;
3769 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3772 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3777 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3780 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3782 for (i = 0; i < tb->num_fields; ++i) {
3783 MonoReflectionFieldBuilder* fb;
3784 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3785 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3789 for (i = 0; i < mono_array_length (tb->events); ++i) {
3790 MonoReflectionEventBuilder* eb;
3791 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3792 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3795 if (tb->properties) {
3796 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3797 MonoReflectionPropertyBuilder* pb;
3798 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3799 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3803 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3804 MonoReflectionCtorBuilder* cb;
3805 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3806 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3807 params_add_cattrs (assembly, cb->pinfo);
3812 for (i = 0; i < tb->num_methods; ++i) {
3813 MonoReflectionMethodBuilder* mb;
3814 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3815 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3816 params_add_cattrs (assembly, mb->pinfo);
3821 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3822 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3827 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3831 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3833 if (moduleb->global_methods) {
3834 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3835 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3836 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3837 params_add_cattrs (assembly, mb->pinfo);
3841 if (moduleb->global_fields) {
3842 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3843 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3844 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3848 if (moduleb->types) {
3849 for (i = 0; i < moduleb->num_types; ++i)
3850 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3855 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3857 MonoDynamicTable *table;
3861 char *b = blob_size;
3864 table = &assembly->tables [MONO_TABLE_FILE];
3866 alloc_table (table, table->rows);
3867 values = table->values + table->next_idx * MONO_FILE_SIZE;
3868 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3869 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3870 if (image_is_dynamic (module->image)) {
3871 /* This depends on the fact that the main module is emitted last */
3872 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3873 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3876 path = g_strdup (module->image->name);
3878 mono_sha1_get_digest_from_file (path, hash);
3881 mono_metadata_encode_value (20, b, &b);
3882 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3883 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3888 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3890 MonoDynamicTable *table;
3893 table = &assembly->tables [MONO_TABLE_MODULE];
3894 mb->table_idx = table->next_idx ++;
3895 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3896 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3899 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3900 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3901 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3902 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3906 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3907 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3909 MonoDynamicTable *table;
3913 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3914 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3917 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3919 alloc_table (table, table->rows);
3920 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3922 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3923 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3924 if (klass->nested_in)
3925 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3927 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3928 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3929 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3931 res = table->next_idx;
3935 /* Emit nested types */
3936 if (klass->ext && klass->ext->nested_classes) {
3939 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3940 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3947 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3948 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3953 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3955 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3957 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3958 parent_index, assembly);
3962 * We need to do this ourselves since klass->nested_classes is not set up.
3965 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3966 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3971 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3972 guint32 module_index, MonoDynamicImage *assembly)
3974 MonoImage *image = module->image;
3978 t = &image->tables [MONO_TABLE_TYPEDEF];
3980 for (i = 0; i < t->rows; ++i) {
3982 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3983 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3985 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3986 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3991 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3993 MonoDynamicTable *table;
3995 guint32 scope, scope_idx, impl, current_idx;
3996 gboolean forwarder = TRUE;
3997 gpointer iter = NULL;
4000 if (klass->nested_in) {
4001 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4004 scope = resolution_scope_from_image (assembly, klass->image);
4005 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4006 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4007 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4010 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4013 alloc_table (table, table->rows);
4014 current_idx = table->next_idx;
4015 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4017 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4018 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4019 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4020 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4021 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4025 while ((nested = mono_class_get_nested_types (klass, &iter)))
4026 add_exported_type (assemblyb, assembly, nested, current_idx);
4030 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4035 if (!assemblyb->type_forwarders)
4038 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4039 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4044 type = mono_reflection_type_get_handle (t);
4047 klass = mono_class_from_mono_type (type);
4049 add_exported_type (assemblyb, assembly, klass, 0);
4053 #define align_pointer(base,p)\
4055 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4057 (p) += 4 - (__diff & 3);\
4061 compare_constants (const void *a, const void *b)
4063 const guint32 *a_values = a;
4064 const guint32 *b_values = b;
4065 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4069 compare_semantics (const void *a, const void *b)
4071 const guint32 *a_values = a;
4072 const guint32 *b_values = b;
4073 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4076 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4080 compare_custom_attrs (const void *a, const void *b)
4082 const guint32 *a_values = a;
4083 const guint32 *b_values = b;
4085 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4089 compare_field_marshal (const void *a, const void *b)
4091 const guint32 *a_values = a;
4092 const guint32 *b_values = b;
4094 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4098 compare_nested (const void *a, const void *b)
4100 const guint32 *a_values = a;
4101 const guint32 *b_values = b;
4103 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4107 compare_genericparam (const void *a, const void *b)
4109 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4110 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4112 if ((*b_entry)->owner == (*a_entry)->owner)
4114 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4115 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4117 return (*a_entry)->owner - (*b_entry)->owner;
4121 compare_declsecurity_attrs (const void *a, const void *b)
4123 const guint32 *a_values = a;
4124 const guint32 *b_values = b;
4126 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4130 compare_interface_impl (const void *a, const void *b)
4132 const guint32 *a_values = a;
4133 const guint32 *b_values = b;
4135 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4139 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4143 pad_heap (MonoDynamicStream *sh)
4145 if (sh->index & 3) {
4146 int sz = 4 - (sh->index & 3);
4147 memset (sh->data + sh->index, 0, sz);
4154 MonoDynamicStream *stream;
4158 * build_compressed_metadata() fills in the blob of data that represents the
4159 * raw metadata as it will be saved in the PE file. The five streams are output
4160 * and the metadata tables are comnpressed from the guint32 array representation,
4161 * to the compressed on-disk format.
4164 build_compressed_metadata (MonoDynamicImage *assembly)
4166 MonoDynamicTable *table;
4168 guint64 valid_mask = 0;
4169 guint64 sorted_mask;
4170 guint32 heapt_size = 0;
4171 guint32 meta_size = 256; /* allow for header and other stuff */
4172 guint32 table_offset;
4173 guint32 ntables = 0;
4179 struct StreamDesc stream_desc [5];
4181 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4182 for (i = 0; i < assembly->gen_params->len; i++){
4183 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4184 write_generic_param_entry (assembly, entry);
4187 stream_desc [0].name = "#~";
4188 stream_desc [0].stream = &assembly->tstream;
4189 stream_desc [1].name = "#Strings";
4190 stream_desc [1].stream = &assembly->sheap;
4191 stream_desc [2].name = "#US";
4192 stream_desc [2].stream = &assembly->us;
4193 stream_desc [3].name = "#Blob";
4194 stream_desc [3].stream = &assembly->blob;
4195 stream_desc [4].name = "#GUID";
4196 stream_desc [4].stream = &assembly->guid;
4198 /* tables that are sorted */
4199 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4200 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4201 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4202 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4203 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4204 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4205 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4207 /* Compute table sizes */
4208 /* the MonoImage has already been created in mono_image_basic_init() */
4209 meta = &assembly->image;
4211 /* sizes should be multiple of 4 */
4212 pad_heap (&assembly->blob);
4213 pad_heap (&assembly->guid);
4214 pad_heap (&assembly->sheap);
4215 pad_heap (&assembly->us);
4217 /* Setup the info used by compute_sizes () */
4218 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4219 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4220 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4222 meta_size += assembly->blob.index;
4223 meta_size += assembly->guid.index;
4224 meta_size += assembly->sheap.index;
4225 meta_size += assembly->us.index;
4227 for (i=0; i < MONO_TABLE_NUM; ++i)
4228 meta->tables [i].rows = assembly->tables [i].rows;
4230 for (i = 0; i < MONO_TABLE_NUM; i++){
4231 if (meta->tables [i].rows == 0)
4233 valid_mask |= (guint64)1 << i;
4235 meta->tables [i].row_size = mono_metadata_compute_size (
4236 meta, i, &meta->tables [i].size_bitfield);
4237 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4239 heapt_size += 24; /* #~ header size */
4240 heapt_size += ntables * 4;
4241 /* make multiple of 4 */
4244 meta_size += heapt_size;
4245 meta->raw_metadata = g_malloc0 (meta_size);
4246 p = (unsigned char*)meta->raw_metadata;
4247 /* the metadata signature */
4248 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4249 /* version numbers and 4 bytes reserved */
4250 int16val = (guint16*)p;
4251 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4252 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4254 /* version string */
4255 int32val = (guint32*)p;
4256 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4258 memcpy (p, meta->version, strlen (meta->version));
4259 p += GUINT32_FROM_LE (*int32val);
4260 align_pointer (meta->raw_metadata, p);
4261 int16val = (guint16*)p;
4262 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4263 *int16val = GUINT16_TO_LE (5); /* number of streams */
4267 * write the stream info.
4269 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4270 table_offset += 3; table_offset &= ~3;
4272 assembly->tstream.index = heapt_size;
4273 for (i = 0; i < 5; ++i) {
4274 int32val = (guint32*)p;
4275 stream_desc [i].stream->offset = table_offset;
4276 *int32val++ = GUINT32_TO_LE (table_offset);
4277 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4278 table_offset += GUINT32_FROM_LE (*int32val);
4279 table_offset += 3; table_offset &= ~3;
4281 strcpy ((char*)p, stream_desc [i].name);
4282 p += strlen (stream_desc [i].name) + 1;
4283 align_pointer (meta->raw_metadata, p);
4286 * now copy the data, the table stream header and contents goes first.
4288 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4289 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4290 int32val = (guint32*)p;
4291 *int32val = GUINT32_TO_LE (0); /* reserved */
4294 *p++ = 2; /* version */
4297 if (meta->idx_string_wide)
4299 if (meta->idx_guid_wide)
4301 if (meta->idx_blob_wide)
4304 *p++ = 1; /* reserved */
4305 int64val = (guint64*)p;
4306 *int64val++ = GUINT64_TO_LE (valid_mask);
4307 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4309 int32val = (guint32*)p;
4310 for (i = 0; i < MONO_TABLE_NUM; i++){
4311 if (meta->tables [i].rows == 0)
4313 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4315 p = (unsigned char*)int32val;
4317 /* sort the tables that still need sorting */
4318 table = &assembly->tables [MONO_TABLE_CONSTANT];
4320 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4321 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4323 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4324 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4326 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4327 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4329 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4330 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4332 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4333 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4334 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4336 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4337 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4339 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4341 /* compress the tables */
4342 for (i = 0; i < MONO_TABLE_NUM; i++){
4345 guint32 bitfield = meta->tables [i].size_bitfield;
4346 if (!meta->tables [i].rows)
4348 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4349 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4350 meta->tables [i].base = (char*)p;
4351 for (row = 1; row <= meta->tables [i].rows; ++row) {
4352 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4353 for (col = 0; col < assembly->tables [i].columns; ++col) {
4354 switch (mono_metadata_table_size (bitfield, col)) {
4356 *p++ = values [col];
4359 *p++ = values [col] & 0xff;
4360 *p++ = (values [col] >> 8) & 0xff;
4363 *p++ = values [col] & 0xff;
4364 *p++ = (values [col] >> 8) & 0xff;
4365 *p++ = (values [col] >> 16) & 0xff;
4366 *p++ = (values [col] >> 24) & 0xff;
4369 g_assert_not_reached ();
4373 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4376 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4377 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4378 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4379 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4380 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4382 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4386 * Some tables in metadata need to be sorted according to some criteria, but
4387 * when methods and fields are first created with reflection, they may be assigned a token
4388 * that doesn't correspond to the final token they will get assigned after the sorting.
4389 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4390 * with the reflection objects that represent them. Once all the tables are set up, the
4391 * reflection objects will contains the correct table index. fixup_method() will fixup the
4392 * tokens for the method with ILGenerator @ilgen.
4395 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4397 guint32 code_idx = GPOINTER_TO_UINT (value);
4398 MonoReflectionILTokenInfo *iltoken;
4399 MonoReflectionFieldBuilder *field;
4400 MonoReflectionCtorBuilder *ctor;
4401 MonoReflectionMethodBuilder *method;
4402 MonoReflectionTypeBuilder *tb;
4403 MonoReflectionArrayMethod *am;
4405 unsigned char *target;
4407 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4408 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4409 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4410 switch (target [3]) {
4411 case MONO_TABLE_FIELD:
4412 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4413 field = (MonoReflectionFieldBuilder *)iltoken->member;
4414 idx = field->table_idx;
4415 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4416 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4417 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4419 g_assert_not_reached ();
4422 case MONO_TABLE_METHOD:
4423 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4424 method = (MonoReflectionMethodBuilder *)iltoken->member;
4425 idx = method->table_idx;
4426 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4427 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4428 idx = ctor->table_idx;
4429 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4430 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4431 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4432 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4434 g_assert_not_reached ();
4437 case MONO_TABLE_TYPEDEF:
4438 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4439 g_assert_not_reached ();
4440 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4441 idx = tb->table_idx;
4443 case MONO_TABLE_MEMBERREF:
4444 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4445 am = (MonoReflectionArrayMethod*)iltoken->member;
4446 idx = am->table_idx;
4447 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4448 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4449 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4450 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4451 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4452 g_assert (m->klass->generic_class || m->klass->generic_container);
4454 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4456 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4457 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4458 g_assert (is_field_on_inst (f));
4460 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4461 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4463 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4465 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4467 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4470 g_assert_not_reached ();
4473 case MONO_TABLE_METHODSPEC:
4474 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4475 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4476 g_assert (mono_method_signature (m)->generic_param_count);
4478 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4480 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4483 g_assert_not_reached ();
4487 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4489 target [0] = idx & 0xff;
4490 target [1] = (idx >> 8) & 0xff;
4491 target [2] = (idx >> 16) & 0xff;
4498 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4499 * value is not known when the table is emitted.
4502 fixup_cattrs (MonoDynamicImage *assembly)
4504 MonoDynamicTable *table;
4506 guint32 type, i, idx, token;
4509 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4511 for (i = 0; i < table->rows; ++i) {
4512 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4514 type = values [MONO_CUSTOM_ATTR_TYPE];
4515 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4516 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4517 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4518 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4521 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4522 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4523 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4524 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4525 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4526 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4527 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4528 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4535 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4537 MonoDynamicTable *table;
4540 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4542 alloc_table (table, table->rows);
4543 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4544 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4545 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4546 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4547 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4552 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4554 MonoDynamicTable *table;
4558 char *b = blob_size;
4560 guint32 idx, offset;
4562 if (rsrc->filename) {
4563 name = mono_string_to_utf8 (rsrc->filename);
4564 sname = g_path_get_basename (name);
4566 table = &assembly->tables [MONO_TABLE_FILE];
4568 alloc_table (table, table->rows);
4569 values = table->values + table->next_idx * MONO_FILE_SIZE;
4570 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4571 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4574 mono_sha1_get_digest_from_file (name, hash);
4575 mono_metadata_encode_value (20, b, &b);
4576 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4577 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4579 idx = table->next_idx++;
4581 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4587 data = mono_array_addr (rsrc->data, char, 0);
4588 len = mono_array_length (rsrc->data);
4594 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4595 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4596 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4597 mono_image_add_stream_data (&assembly->resources, data, len);
4601 * The entry should be emitted into the MANIFESTRESOURCE table of
4602 * the main module, but that needs to reference the FILE table
4603 * which isn't emitted yet.
4610 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4614 set_version_from_string (MonoString *version, guint32 *values)
4616 gchar *ver, *p, *str;
4619 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4620 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4621 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4622 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4625 ver = str = mono_string_to_utf8 (version);
4626 for (i = 0; i < 4; ++i) {
4627 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4633 /* handle Revision and Build */
4643 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4647 char *b = blob_size;
4652 len = mono_array_length (pkey);
4653 mono_metadata_encode_value (len, b, &b);
4654 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4655 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4657 assembly->public_key = g_malloc (len);
4658 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4659 assembly->public_key_len = len;
4661 /* Special case: check for ECMA key (16 bytes) */
4662 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4663 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4664 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4665 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4666 /* minimum key size (in 2.0) is 384 bits */
4667 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4669 /* FIXME - verifier */
4670 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4671 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4673 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4679 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4681 MonoDynamicTable *table;
4682 MonoDynamicImage *assembly;
4683 MonoReflectionAssemblyBuilder *assemblyb;
4687 guint32 module_index;
4689 assemblyb = moduleb->assemblyb;
4690 assembly = moduleb->dynamic_image;
4691 domain = mono_object_domain (assemblyb);
4693 /* Emit ASSEMBLY table */
4694 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4695 alloc_table (table, 1);
4696 values = table->values + MONO_ASSEMBLY_SIZE;
4697 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4698 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4699 if (assemblyb->culture) {
4700 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4702 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4704 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4705 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4706 set_version_from_string (assemblyb->version, values);
4708 /* Emit FILE + EXPORTED_TYPE table */
4710 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4712 MonoReflectionModuleBuilder *file_module =
4713 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4714 if (file_module != moduleb) {
4715 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4717 if (file_module->types) {
4718 for (j = 0; j < file_module->num_types; ++j) {
4719 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4720 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4725 if (assemblyb->loaded_modules) {
4726 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4727 MonoReflectionModule *file_module =
4728 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4729 mono_image_fill_file_table (domain, file_module, assembly);
4731 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4734 if (assemblyb->type_forwarders)
4735 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4737 /* Emit MANIFESTRESOURCE table */
4739 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4741 MonoReflectionModuleBuilder *file_module =
4742 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4743 /* The table for the main module is emitted later */
4744 if (file_module != moduleb) {
4746 if (file_module->resources) {
4747 int len = mono_array_length (file_module->resources);
4748 for (j = 0; j < len; ++j) {
4749 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4750 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4757 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4760 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4761 * for the modulebuilder @moduleb.
4762 * At the end of the process, method and field tokens are fixed up and the
4763 * on-disk compressed metadata representation is created.
4766 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4768 MonoDynamicTable *table;
4769 MonoDynamicImage *assembly;
4770 MonoReflectionAssemblyBuilder *assemblyb;
4776 assemblyb = moduleb->assemblyb;
4777 assembly = moduleb->dynamic_image;
4778 domain = mono_object_domain (assemblyb);
4780 if (assembly->text_rva)
4783 assembly->text_rva = START_TEXT_RVA;
4785 if (moduleb->is_main) {
4786 mono_image_emit_manifest (moduleb);
4789 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4790 table->rows = 1; /* .<Module> */
4792 alloc_table (table, table->rows);
4794 * Set the first entry.
4796 values = table->values + table->columns;
4797 values [MONO_TYPEDEF_FLAGS] = 0;
4798 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4799 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4800 values [MONO_TYPEDEF_EXTENDS] = 0;
4801 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4802 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4805 * handle global methods
4806 * FIXME: test what to do when global methods are defined in multiple modules.
4808 if (moduleb->global_methods) {
4809 table = &assembly->tables [MONO_TABLE_METHOD];
4810 table->rows += mono_array_length (moduleb->global_methods);
4811 alloc_table (table, table->rows);
4812 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4813 mono_image_get_method_info (
4814 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4816 if (moduleb->global_fields) {
4817 table = &assembly->tables [MONO_TABLE_FIELD];
4818 table->rows += mono_array_length (moduleb->global_fields);
4819 alloc_table (table, table->rows);
4820 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4821 mono_image_get_field_info (
4822 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4825 table = &assembly->tables [MONO_TABLE_MODULE];
4826 alloc_table (table, 1);
4827 mono_image_fill_module_table (domain, moduleb, assembly);
4829 /* Collect all types into a list sorted by their table_idx */
4830 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4833 for (i = 0; i < moduleb->num_types; ++i) {
4834 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4835 collect_types (&types, type);
4838 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840 table->rows += mono_ptr_array_size (types);
4841 alloc_table (table, table->rows);
4844 * Emit type names + namespaces at one place inside the string heap,
4845 * so load_class_names () needs to touch fewer pages.
4847 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4848 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4849 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4851 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4852 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4853 string_heap_insert_mstring (&assembly->sheap, tb->name);
4856 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4857 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4858 mono_image_get_type_info (domain, type, assembly);
4862 * table->rows is already set above and in mono_image_fill_module_table.
4864 /* add all the custom attributes at the end, once all the indexes are stable */
4865 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4867 /* CAS assembly permissions */
4868 if (assemblyb->permissions_minimum)
4869 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4870 if (assemblyb->permissions_optional)
4871 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4872 if (assemblyb->permissions_refused)
4873 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4875 module_add_cattrs (assembly, moduleb);
4878 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4880 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4881 * the final tokens and don't need another fixup pass. */
4883 if (moduleb->global_methods) {
4884 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4885 MonoReflectionMethodBuilder *mb = mono_array_get (
4886 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4887 mono_image_add_methodimpl (assembly, mb);
4891 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4892 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4893 if (type->methods) {
4894 for (j = 0; j < type->num_methods; ++j) {
4895 MonoReflectionMethodBuilder *mb = mono_array_get (
4896 type->methods, MonoReflectionMethodBuilder*, j);
4898 mono_image_add_methodimpl (assembly, mb);
4903 mono_ptr_array_destroy (types);
4905 fixup_cattrs (assembly);
4908 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4911 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4913 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4916 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4920 guint32 import_lookup_table;
4924 guint32 import_address_table_rva;
4932 #ifndef DISABLE_REFLECTION_EMIT
4935 * mono_image_insert_string:
4936 * @module: module builder object
4939 * Insert @str into the user string stream of @module.
4942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4944 MonoDynamicImage *assembly;
4949 if (!module->dynamic_image)
4950 mono_image_module_basic_init (module);
4952 assembly = module->dynamic_image;
4954 if (assembly->save) {
4955 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4956 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4957 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4959 char *swapped = g_malloc (2 * mono_string_length (str));
4960 const char *p = (const char*)mono_string_chars (str);
4962 swap_with_size (swapped, p, 2, mono_string_length (str));
4963 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4967 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4969 mono_image_add_stream_data (&assembly->us, "", 1);
4971 idx = assembly->us.index ++;
4974 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4976 return MONO_TOKEN_STRING | idx;
4980 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4984 MonoMethodSignature *sig;
4986 klass = obj->vtable->klass;
4987 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4988 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4989 MonoMethodSignature *old;
4990 guint32 sig_token, parent;
4993 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4995 nargs = mono_array_length (opt_param_types);
4996 old = mono_method_signature (method);
4997 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4999 sig->hasthis = old->hasthis;
5000 sig->explicit_this = old->explicit_this;
5001 sig->call_convention = old->call_convention;
5002 sig->generic_param_count = old->generic_param_count;
5003 sig->param_count = old->param_count + nargs;
5004 sig->sentinelpos = old->param_count;
5005 sig->ret = old->ret;
5007 for (i = 0; i < old->param_count; i++)
5008 sig->params [i] = old->params [i];
5010 for (i = 0; i < nargs; i++) {
5011 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5012 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5015 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5016 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5017 parent >>= MONO_TYPEDEFORREF_BITS;
5019 parent <<= MONO_MEMBERREF_PARENT_BITS;
5020 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5022 sig_token = method_encode_signature (assembly, sig);
5023 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5024 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5025 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5026 ReflectionMethodBuilder rmb;
5027 guint32 parent, sig_token;
5028 int nopt_args, nparams, ngparams, i;
5031 reflection_methodbuilder_from_method_builder (&rmb, mb);
5032 rmb.opt_types = opt_param_types;
5033 nopt_args = mono_array_length (opt_param_types);
5035 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5036 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5037 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5039 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5040 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5041 sig->call_convention = rmb.call_conv;
5042 sig->generic_param_count = ngparams;
5043 sig->param_count = nparams + nopt_args;
5044 sig->sentinelpos = nparams;
5045 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5047 for (i = 0; i < nparams; i++) {
5048 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5049 sig->params [i] = mono_reflection_type_get_handle (rt);
5052 for (i = 0; i < nopt_args; i++) {
5053 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5057 sig_token = method_builder_encode_signature (assembly, &rmb);
5059 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5060 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5062 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5063 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5065 name = mono_string_to_utf8 (rmb.name);
5066 token = mono_image_get_varargs_method_token (
5067 assembly, parent, name, sig_token);
5070 g_error ("requested method token for %s\n", klass->name);
5073 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5074 register_dyn_token (assembly, token, obj);
5079 * mono_image_create_token:
5080 * @assembly: a dynamic assembly
5082 * @register_token: Whenever to register the token in the assembly->tokens hash.
5084 * Get a token to insert in the IL code stream for the given MemberInfo.
5085 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5086 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5090 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5091 gboolean create_open_instance, gboolean register_token)
5096 klass = obj->vtable->klass;
5098 /* Check for user defined reflection objects */
5099 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5100 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5101 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5103 if (strcmp (klass->name, "MethodBuilder") == 0) {
5104 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5105 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5107 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5108 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5110 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5111 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5112 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5113 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5114 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5116 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5117 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5119 token = mono_image_get_ctorbuilder_token (assembly, mb);
5120 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5121 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5122 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5123 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5124 if (tb->generic_params) {
5125 token = mono_image_get_generic_field_token (assembly, fb);
5127 if (tb->module->dynamic_image == assembly) {
5128 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5130 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5133 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5134 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5135 if (create_open_instance && tb->generic_params) {
5137 init_type_builder_generics (obj);
5138 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5139 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5140 token = mono_metadata_token_from_dor (token);
5141 } else if (tb->module->dynamic_image == assembly) {
5142 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5145 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5146 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5148 } else if (strcmp (klass->name, "MonoType") == 0) {
5149 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5150 MonoClass *mc = mono_class_from_mono_type (type);
5151 token = mono_metadata_token_from_dor (
5152 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5153 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5154 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5155 token = mono_metadata_token_from_dor (
5156 mono_image_typedef_or_ref (assembly, type));
5157 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5158 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5159 token = mono_metadata_token_from_dor (
5160 mono_image_typedef_or_ref (assembly, type));
5161 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5162 strcmp (klass->name, "MonoMethod") == 0 ||
5163 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5164 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5165 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5166 if (m->method->is_inflated) {
5167 if (create_open_instance)
5168 token = mono_image_get_methodspec_token (assembly, m->method);
5170 token = mono_image_get_inflated_method_token (assembly, m->method);
5171 } else if ((m->method->klass->image == &assembly->image) &&
5172 !m->method->klass->generic_class) {
5173 static guint32 method_table_idx = 0xffffff;
5174 if (m->method->klass->wastypebuilder) {
5175 /* we use the same token as the one that was assigned
5176 * to the Methodbuilder.
5177 * FIXME: do the equivalent for Fields.
5179 token = m->method->token;
5182 * Each token should have a unique index, but the indexes are
5183 * assigned by managed code, so we don't know about them. An
5184 * easy solution is to count backwards...
5186 method_table_idx --;
5187 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5190 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5192 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5193 } else if (strcmp (klass->name, "MonoField") == 0) {
5194 MonoReflectionField *f = (MonoReflectionField *)obj;
5195 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5196 static guint32 field_table_idx = 0xffffff;
5198 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5200 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5202 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5203 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5204 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5205 token = mono_image_get_array_token (assembly, m);
5206 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5207 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5208 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5209 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5210 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5211 token = mono_metadata_token_from_dor (
5212 mono_image_typedef_or_ref (assembly, type));
5213 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5214 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5215 token = mono_image_get_field_on_inst_token (assembly, f);
5216 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5217 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5218 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5219 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5220 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5221 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5222 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5223 MonoReflectionType *type = (MonoReflectionType *)obj;
5224 token = mono_metadata_token_from_dor (
5225 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5227 g_error ("requested token for %s\n", klass->name);
5231 mono_image_register_token (assembly, token, obj);
5237 * mono_image_register_token:
5239 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5240 * the Module.ResolveXXXToken () methods to work.
5243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5247 dynamic_image_lock (assembly);
5248 prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5250 /* There could be multiple MethodInfo objects with the same token */
5251 //g_assert (prev == obj);
5253 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5255 dynamic_image_unlock (assembly);
5258 static MonoDynamicImage*
5259 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5261 static const guchar entrycode [16] = {0xff, 0x25, 0};
5262 MonoDynamicImage *image;
5265 const char *version;
5267 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5268 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5270 version = mono_get_runtime_info ()->runtime_version;
5273 /* The MonoGHashTable's need GC tracking */
5274 image = GC_MALLOC (sizeof (MonoDynamicImage));
5276 image = g_new0 (MonoDynamicImage, 1);
5279 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5281 /*g_print ("created image %p\n", image);*/
5282 /* keep in sync with image.c */
5283 image->image.name = assembly_name;
5284 image->image.assembly_name = image->image.name; /* they may be different */
5285 image->image.module_name = module_name;
5286 image->image.version = g_strdup (version);
5287 image->image.md_version_major = 1;
5288 image->image.md_version_minor = 1;
5289 image->image.dynamic = TRUE;
5291 image->image.references = g_new0 (MonoAssembly*, 1);
5292 image->image.references [0] = NULL;
5294 mono_image_init (&image->image);
5296 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5297 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5298 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5299 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5300 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5301 image->handleref = g_hash_table_new (NULL, NULL);
5302 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5303 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5304 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5305 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5306 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5307 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5308 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5309 image->gen_params = g_ptr_array_new ();
5310 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5312 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5313 string_heap_init (&image->sheap);
5314 mono_image_add_stream_data (&image->us, "", 1);
5315 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5316 /* import tables... */
5317 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5318 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5319 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5320 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5321 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5322 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5323 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5324 stream_data_align (&image->code);
5326 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5328 for (i=0; i < MONO_TABLE_NUM; ++i) {
5329 image->tables [i].next_idx = 1;
5330 image->tables [i].columns = table_sizes [i];
5333 image->image.assembly = (MonoAssembly*)assembly;
5334 image->run = assembly->run;
5335 image->save = assembly->save;
5336 image->pe_kind = 0x1; /* ILOnly */
5337 image->machine = 0x14c; /* I386 */
5339 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5346 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5352 release_hashtable (MonoGHashTable **hash)
5355 mono_g_hash_table_destroy (*hash);
5361 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5363 release_hashtable (&image->token_fixups);
5364 release_hashtable (&image->handleref_managed);
5365 release_hashtable (&image->tokens);
5366 release_hashtable (&image->remapped_tokens);
5367 release_hashtable (&image->generic_def_objects);
5368 release_hashtable (&image->methodspec);
5372 mono_dynamic_image_free (MonoDynamicImage *image)
5374 MonoDynamicImage *di = image;
5379 mono_g_hash_table_destroy (di->methodspec);
5381 g_hash_table_destroy (di->typespec);
5383 g_hash_table_destroy (di->typeref);
5385 g_hash_table_destroy (di->handleref);
5386 if (di->handleref_managed)
5387 mono_g_hash_table_destroy (di->handleref_managed);
5389 mono_g_hash_table_destroy (di->tokens);
5390 if (di->remapped_tokens)
5391 mono_g_hash_table_destroy (di->remapped_tokens);
5392 if (di->generic_def_objects)
5393 mono_g_hash_table_destroy (di->generic_def_objects);
5394 if (di->blob_cache) {
5395 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5396 g_hash_table_destroy (di->blob_cache);
5398 if (di->standalonesig_cache)
5399 g_hash_table_destroy (di->standalonesig_cache);
5400 for (list = di->array_methods; list; list = list->next) {
5401 ArrayMethod *am = (ArrayMethod *)list->data;
5406 g_list_free (di->array_methods);
5407 if (di->gen_params) {
5408 for (i = 0; i < di->gen_params->len; i++) {
5409 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5410 mono_gc_deregister_root ((char*) &entry->gparam);
5413 g_ptr_array_free (di->gen_params, TRUE);
5415 if (di->token_fixups)
5416 mono_g_hash_table_destroy (di->token_fixups);
5417 if (di->method_to_table_idx)
5418 g_hash_table_destroy (di->method_to_table_idx);
5419 if (di->field_to_table_idx)
5420 g_hash_table_destroy (di->field_to_table_idx);
5421 if (di->method_aux_hash)
5422 g_hash_table_destroy (di->method_aux_hash);
5423 if (di->vararg_aux_hash)
5424 g_hash_table_destroy (di->vararg_aux_hash);
5425 g_free (di->strong_name);
5426 g_free (di->win32_res);
5428 g_free (di->public_key);
5430 /*g_print ("string heap destroy for image %p\n", di);*/
5431 mono_dynamic_stream_reset (&di->sheap);
5432 mono_dynamic_stream_reset (&di->code);
5433 mono_dynamic_stream_reset (&di->resources);
5434 mono_dynamic_stream_reset (&di->us);
5435 mono_dynamic_stream_reset (&di->blob);
5436 mono_dynamic_stream_reset (&di->tstream);
5437 mono_dynamic_stream_reset (&di->guid);
5438 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5439 g_free (di->tables [i].values);
5444 mono_dynamic_image_free_image (MonoDynamicImage *image)
5446 /* See create_dynamic_mono_image () */
5448 /* Allocated using GC_MALLOC */
5454 #ifndef DISABLE_REFLECTION_EMIT
5457 * mono_image_basic_init:
5458 * @assembly: an assembly builder object
5460 * Create the MonoImage that represents the assembly builder and setup some
5461 * of the helper hash table and the basic metadata streams.
5464 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5466 MonoDynamicAssembly *assembly;
5467 MonoDynamicImage *image;
5468 MonoDomain *domain = mono_object_domain (assemblyb);
5470 if (assemblyb->dynamic_assembly)
5474 /* assembly->assembly.image might be GC allocated */
5475 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5477 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5480 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5482 assembly->assembly.ref_count = 1;
5483 assembly->assembly.dynamic = TRUE;
5484 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5485 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5486 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5487 if (assemblyb->culture)
5488 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5490 assembly->assembly.aname.culture = g_strdup ("");
5492 if (assemblyb->version) {
5493 char *vstr = mono_string_to_utf8 (assemblyb->version);
5494 char **version = g_strsplit (vstr, ".", 4);
5495 char **parts = version;
5496 assembly->assembly.aname.major = atoi (*parts++);
5497 assembly->assembly.aname.minor = atoi (*parts++);
5498 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5499 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5501 g_strfreev (version);
5504 assembly->assembly.aname.major = 0;
5505 assembly->assembly.aname.minor = 0;
5506 assembly->assembly.aname.build = 0;
5507 assembly->assembly.aname.revision = 0;
5510 assembly->run = assemblyb->access != 2;
5511 assembly->save = assemblyb->access != 1;
5512 assembly->domain = domain;
5514 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5515 image->initial_image = TRUE;
5516 assembly->assembly.aname.name = image->image.name;
5517 assembly->assembly.image = &image->image;
5518 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5519 /* -1 to correct for the trailing NULL byte */
5520 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5521 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5523 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5526 mono_domain_assemblies_lock (domain);
5527 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5528 mono_domain_assemblies_unlock (domain);
5530 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5532 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5534 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5537 #endif /* !DISABLE_REFLECTION_EMIT */
5539 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5542 calc_section_size (MonoDynamicImage *assembly)
5546 /* alignment constraints */
5547 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5548 g_assert ((assembly->code.index % 4) == 0);
5549 assembly->meta_size += 3;
5550 assembly->meta_size &= ~3;
5551 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5552 g_assert ((assembly->resources.index % 4) == 0);
5554 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5555 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5558 if (assembly->win32_res) {
5559 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5561 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5562 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5566 assembly->sections [MONO_SECTION_RELOC].size = 12;
5567 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5577 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5581 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5583 ResTreeNode *t1 = (ResTreeNode*)a;
5584 ResTreeNode *t2 = (ResTreeNode*)b;
5586 return t1->id - t2->id;
5590 * resource_tree_create:
5592 * Organize the resources into a resource tree.
5594 static ResTreeNode *
5595 resource_tree_create (MonoArray *win32_resources)
5597 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5601 tree = g_new0 (ResTreeNode, 1);
5603 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5604 MonoReflectionWin32Resource *win32_res =
5605 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5609 /* FIXME: BUG: this stores managed references in unmanaged memory */
5610 lang_node = g_new0 (ResTreeNode, 1);
5611 lang_node->id = win32_res->lang_id;
5612 lang_node->win32_res = win32_res;
5614 /* Create type node if neccesary */
5616 for (l = tree->children; l; l = l->next)
5617 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5618 type_node = (ResTreeNode*)l->data;
5623 type_node = g_new0 (ResTreeNode, 1);
5624 type_node->id = win32_res->res_type;
5627 * The resource types have to be sorted otherwise
5628 * Windows Explorer can't display the version information.
5630 tree->children = g_slist_insert_sorted (tree->children,
5631 type_node, resource_tree_compare_by_id);
5634 /* Create res node if neccesary */
5636 for (l = type_node->children; l; l = l->next)
5637 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5638 res_node = (ResTreeNode*)l->data;
5643 res_node = g_new0 (ResTreeNode, 1);
5644 res_node->id = win32_res->res_id;
5645 type_node->children = g_slist_append (type_node->children, res_node);
5648 res_node->children = g_slist_append (res_node->children, lang_node);
5655 * resource_tree_encode:
5657 * Encode the resource tree into the format used in the PE file.
5660 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5663 MonoPEResourceDir dir;
5664 MonoPEResourceDirEntry dir_entry;
5665 MonoPEResourceDataEntry data_entry;
5667 guint32 res_id_entries;
5670 * For the format of the resource directory, see the article
5671 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5675 memset (&dir, 0, sizeof (dir));
5676 memset (&dir_entry, 0, sizeof (dir_entry));
5677 memset (&data_entry, 0, sizeof (data_entry));
5679 g_assert (sizeof (dir) == 16);
5680 g_assert (sizeof (dir_entry) == 8);
5681 g_assert (sizeof (data_entry) == 16);
5683 node->offset = p - begin;
5685 /* IMAGE_RESOURCE_DIRECTORY */
5686 res_id_entries = g_slist_length (node->children);
5687 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5689 memcpy (p, &dir, sizeof (dir));
5692 /* Reserve space for entries */
5694 p += sizeof (dir_entry) * res_id_entries;
5696 /* Write children */
5697 for (l = node->children; l; l = l->next) {
5698 ResTreeNode *child = (ResTreeNode*)l->data;
5700 if (child->win32_res) {
5703 child->offset = p - begin;
5705 /* IMAGE_RESOURCE_DATA_ENTRY */
5706 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5707 size = mono_array_length (child->win32_res->res_data);
5708 data_entry.rde_size = GUINT32_TO_LE (size);
5710 memcpy (p, &data_entry, sizeof (data_entry));
5711 p += sizeof (data_entry);
5713 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5716 resource_tree_encode (child, begin, p, &p);
5720 /* IMAGE_RESOURCE_ENTRY */
5721 for (l = node->children; l; l = l->next) {
5722 ResTreeNode *child = (ResTreeNode*)l->data;
5724 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5725 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5727 memcpy (entries, &dir_entry, sizeof (dir_entry));
5728 entries += sizeof (dir_entry);
5735 resource_tree_free (ResTreeNode * node)
5738 for (list = node->children; list; list = list->next)
5739 resource_tree_free ((ResTreeNode*)list->data);
5740 g_slist_free(node->children);
5745 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5750 MonoReflectionWin32Resource *win32_res;
5753 if (!assemblyb->win32_resources)
5757 * Resources are stored in a three level tree inside the PE file.
5758 * - level one contains a node for each type of resource
5759 * - level two contains a node for each resource
5760 * - level three contains a node for each instance of a resource for a
5761 * specific language.
5764 tree = resource_tree_create (assemblyb->win32_resources);
5766 /* Estimate the size of the encoded tree */
5768 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5769 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5770 size += mono_array_length (win32_res->res_data);
5772 /* Directory structure */
5773 size += mono_array_length (assemblyb->win32_resources) * 256;
5774 p = buf = g_malloc (size);
5776 resource_tree_encode (tree, p, p, &p);
5778 g_assert (p - buf <= size);
5780 assembly->win32_res = g_malloc (p - buf);
5781 assembly->win32_res_size = p - buf;
5782 memcpy (assembly->win32_res, buf, p - buf);
5785 resource_tree_free (tree);
5789 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5791 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5794 p += sizeof (MonoPEResourceDir);
5795 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5796 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5797 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5798 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5799 fixup_resource_directory (res_section, child, rva);
5801 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5802 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5805 p += sizeof (MonoPEResourceDirEntry);
5810 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5813 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5814 g_error ("WriteFile returned %d\n", GetLastError ());
5818 * mono_image_create_pefile:
5819 * @mb: a module builder object
5821 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5822 * assembly->pefile where it can be easily retrieved later in chunks.
5825 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5827 MonoMSDOSHeader *msdos;
5828 MonoDotNetHeader *header;
5829 MonoSectionTable *section;
5830 MonoCLIHeader *cli_header;
5831 guint32 size, image_size, virtual_base, text_offset;
5832 guint32 header_start, section_start, file_offset, virtual_offset;
5833 MonoDynamicImage *assembly;
5834 MonoReflectionAssemblyBuilder *assemblyb;
5835 MonoDynamicStream pefile_stream = {0};
5836 MonoDynamicStream *pefile = &pefile_stream;
5838 guint32 *rva, value;
5840 static const unsigned char msheader[] = {
5841 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5842 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5845 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5846 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5847 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5848 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5851 assemblyb = mb->assemblyb;
5853 mono_image_basic_init (assemblyb);
5854 assembly = mb->dynamic_image;
5856 assembly->pe_kind = assemblyb->pe_kind;
5857 assembly->machine = assemblyb->machine;
5858 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5859 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5861 mono_image_build_metadata (mb);
5863 if (mb->is_main && assemblyb->resources) {
5864 int len = mono_array_length (assemblyb->resources);
5865 for (i = 0; i < len; ++i)
5866 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5869 if (mb->resources) {
5870 int len = mono_array_length (mb->resources);
5871 for (i = 0; i < len; ++i)
5872 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5875 build_compressed_metadata (assembly);
5878 assembly_add_win32_resources (assembly, assemblyb);
5880 nsections = calc_section_size (assembly);
5882 /* The DOS header and stub */
5883 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5884 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5886 /* the dotnet header */
5887 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5889 /* the section tables */
5890 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5892 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5893 virtual_offset = VIRT_ALIGN;
5896 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897 if (!assembly->sections [i].size)
5900 file_offset += FILE_ALIGN - 1;
5901 file_offset &= ~(FILE_ALIGN - 1);
5902 virtual_offset += VIRT_ALIGN - 1;
5903 virtual_offset &= ~(VIRT_ALIGN - 1);
5905 assembly->sections [i].offset = file_offset;
5906 assembly->sections [i].rva = virtual_offset;
5908 file_offset += assembly->sections [i].size;
5909 virtual_offset += assembly->sections [i].size;
5910 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5913 file_offset += FILE_ALIGN - 1;
5914 file_offset &= ~(FILE_ALIGN - 1);
5916 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5918 /* back-patch info */
5919 msdos = (MonoMSDOSHeader*)pefile->data;
5920 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5922 header = (MonoDotNetHeader*)(pefile->data + header_start);
5923 header->pesig [0] = 'P';
5924 header->pesig [1] = 'E';
5926 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5927 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5928 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5929 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5930 if (assemblyb->pekind == 1) {
5932 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5935 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5938 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5940 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5941 header->pe.pe_major = 6;
5942 header->pe.pe_minor = 0;
5943 size = assembly->sections [MONO_SECTION_TEXT].size;
5944 size += FILE_ALIGN - 1;
5945 size &= ~(FILE_ALIGN - 1);
5946 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5947 size = assembly->sections [MONO_SECTION_RSRC].size;
5948 size += FILE_ALIGN - 1;
5949 size &= ~(FILE_ALIGN - 1);
5950 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5951 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5952 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5953 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5954 /* pe_rva_entry_point always at the beginning of the text section */
5955 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5957 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5958 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5959 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5960 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5961 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5962 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5963 size = section_start;
5964 size += FILE_ALIGN - 1;
5965 size &= ~(FILE_ALIGN - 1);
5966 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5968 size += VIRT_ALIGN - 1;
5969 size &= ~(VIRT_ALIGN - 1);
5970 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5973 // Translate the PEFileKind value to the value expected by the Windows loader
5979 // PEFileKinds.Dll == 1
5980 // PEFileKinds.ConsoleApplication == 2
5981 // PEFileKinds.WindowApplication == 3
5984 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5985 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5987 if (assemblyb->pekind == 3)
5992 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5994 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5995 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5996 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5997 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5998 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5999 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6001 /* fill data directory entries */
6003 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6004 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6006 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6007 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6009 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6010 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6011 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6012 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6013 /* patch entrypoint name */
6014 if (assemblyb->pekind == 1)
6015 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6017 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6018 /* patch imported function RVA name */
6019 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6020 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6022 /* the import table */
6023 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6024 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6025 /* patch imported dll RVA name and other entries in the dir */
6026 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6027 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6028 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6029 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6030 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6031 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6033 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6034 value = (assembly->text_rva + assembly->imp_names_offset);
6035 *p++ = (value) & 0xff;
6036 *p++ = (value >> 8) & (0xff);
6037 *p++ = (value >> 16) & (0xff);
6038 *p++ = (value >> 24) & (0xff);
6040 /* the CLI header info */
6041 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6042 cli_header->ch_size = GUINT32_FROM_LE (72);
6043 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6044 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6045 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6046 if (assemblyb->entry_point) {
6047 guint32 table_idx = 0;
6048 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6049 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6050 table_idx = methodb->table_idx;
6052 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6054 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6056 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6058 /* The embedded managed resources */
6059 text_offset = assembly->text_rva + assembly->code.index;
6060 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6061 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6062 text_offset += assembly->resources.index;
6063 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6064 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6065 text_offset += assembly->meta_size;
6066 if (assembly->strong_name_size) {
6067 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6068 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6069 text_offset += assembly->strong_name_size;
6072 /* write the section tables and section content */
6073 section = (MonoSectionTable*)(pefile->data + section_start);
6074 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6075 static const char section_names [][7] = {
6076 ".text", ".rsrc", ".reloc"
6078 if (!assembly->sections [i].size)
6080 strcpy (section->st_name, section_names [i]);
6081 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6082 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6083 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6084 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6085 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6086 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6087 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6091 checked_write_file (file, pefile->data, pefile->index);
6093 mono_dynamic_stream_reset (pefile);
6095 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6096 if (!assembly->sections [i].size)
6099 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6100 g_error ("SetFilePointer returned %d\n", GetLastError ());
6103 case MONO_SECTION_TEXT:
6104 /* patch entry point */
6105 p = (guchar*)(assembly->code.data + 2);
6106 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6107 *p++ = (value) & 0xff;
6108 *p++ = (value >> 8) & 0xff;
6109 *p++ = (value >> 16) & 0xff;
6110 *p++ = (value >> 24) & 0xff;
6112 checked_write_file (file, assembly->code.data, assembly->code.index);
6113 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6114 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6115 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6118 g_free (assembly->image.raw_metadata);
6120 case MONO_SECTION_RELOC: {
6124 guint16 type_and_offset;
6128 g_assert (sizeof (reloc) == 12);
6130 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6131 reloc.block_size = GUINT32_FROM_LE (12);
6134 * the entrypoint is always at the start of the text section
6135 * 3 is IMAGE_REL_BASED_HIGHLOW
6136 * 2 is patch_size_rva - text_rva
6138 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6141 checked_write_file (file, &reloc, sizeof (reloc));
6145 case MONO_SECTION_RSRC:
6146 if (assembly->win32_res) {
6148 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6149 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6150 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6154 g_assert_not_reached ();
6158 /* check that the file is properly padded */
6159 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160 g_error ("SetFilePointer returned %d\n", GetLastError ());
6161 if (! SetEndOfFile (file))
6162 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6164 mono_dynamic_stream_reset (&assembly->code);
6165 mono_dynamic_stream_reset (&assembly->us);
6166 mono_dynamic_stream_reset (&assembly->blob);
6167 mono_dynamic_stream_reset (&assembly->guid);
6168 mono_dynamic_stream_reset (&assembly->sheap);
6170 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6171 g_hash_table_destroy (assembly->blob_cache);
6172 assembly->blob_cache = NULL;
6175 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6178 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6180 g_assert_not_reached ();
6183 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6185 #ifndef DISABLE_REFLECTION_EMIT
6187 MonoReflectionModule *
6188 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6192 MonoImageOpenStatus status;
6193 MonoDynamicAssembly *assembly;
6194 guint32 module_count;
6195 MonoImage **new_modules;
6196 gboolean *new_modules_loaded;
6198 name = mono_string_to_utf8 (fileName);
6200 image = mono_image_open (name, &status);
6203 if (status == MONO_IMAGE_ERROR_ERRNO)
6204 exc = mono_get_exception_file_not_found (fileName);
6206 exc = mono_get_exception_bad_image_format (name);
6208 mono_raise_exception (exc);
6213 assembly = ab->dynamic_assembly;
6214 image->assembly = (MonoAssembly*)assembly;
6216 module_count = image->assembly->image->module_count;
6217 new_modules = g_new0 (MonoImage *, module_count + 1);
6218 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6220 if (image->assembly->image->modules)
6221 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6222 if (image->assembly->image->modules_loaded)
6223 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6224 new_modules [module_count] = image;
6225 new_modules_loaded [module_count] = TRUE;
6226 mono_image_addref (image);
6228 g_free (image->assembly->image->modules);
6229 image->assembly->image->modules = new_modules;
6230 image->assembly->image->modules_loaded = new_modules_loaded;
6231 image->assembly->image->module_count ++;
6233 mono_assembly_load_references (image, &status);
6235 mono_image_close (image);
6236 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6239 return mono_module_get_object (mono_domain_get (), image);
6242 #endif /* DISABLE_REFLECTION_EMIT */
6245 * We need to return always the same object for MethodInfo, FieldInfo etc..
6246 * but we need to consider the reflected type.
6247 * type uses a different hash, since it uses custom hash/equal functions.
6252 MonoClass *refclass;
6256 reflected_equal (gconstpointer a, gconstpointer b) {
6257 const ReflectedEntry *ea = a;
6258 const ReflectedEntry *eb = b;
6260 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6264 reflected_hash (gconstpointer a) {
6265 const ReflectedEntry *ea = a;
6266 return mono_aligned_addr_hash (ea->item);
6269 #define CHECK_OBJECT(t,p,k) \
6275 mono_domain_lock (domain); \
6276 if (!domain->refobject_hash) \
6277 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6278 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6279 mono_domain_unlock (domain); \
6282 mono_domain_unlock (domain); \
6285 #ifdef HAVE_BOEHM_GC
6286 /* ReflectedEntry doesn't need to be GC tracked */
6287 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6288 #define FREE_REFENTRY(entry) g_free ((entry))
6289 #define REFENTRY_REQUIRES_CLEANUP
6291 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6293 #define FREE_REFENTRY(entry)
6296 #define CACHE_OBJECT(t,p,o,k) \
6299 ReflectedEntry pe; \
6301 pe.refclass = (k); \
6302 mono_domain_lock (domain); \
6303 if (!domain->refobject_hash) \
6304 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6305 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6307 ReflectedEntry *e = ALLOC_REFENTRY; \
6309 e->refclass = (k); \
6310 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6313 mono_domain_unlock (domain); \
6318 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6320 mono_domain_lock (domain);
6321 if (domain->refobject_hash) {
6323 gpointer orig_pe, orig_value;
6326 pe.refclass = klass;
6327 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6328 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6329 FREE_REFENTRY (orig_pe);
6332 mono_domain_unlock (domain);
6335 #ifdef REFENTRY_REQUIRES_CLEANUP
6337 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6339 FREE_REFENTRY (key);
6344 mono_reflection_cleanup_domain (MonoDomain *domain)
6346 if (domain->refobject_hash) {
6347 /*let's avoid scanning the whole hashtable if not needed*/
6348 #ifdef REFENTRY_REQUIRES_CLEANUP
6349 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6351 mono_g_hash_table_destroy (domain->refobject_hash);
6352 domain->refobject_hash = NULL;
6356 #ifndef DISABLE_REFLECTION_EMIT
6358 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6360 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6364 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6366 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6370 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6372 MonoDynamicImage *image = moduleb->dynamic_image;
6373 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6377 MonoImage **new_modules;
6379 char *name, *fqname;
6381 * FIXME: we already created an image in mono_image_basic_init (), but
6382 * we don't know which module it belongs to, since that is only
6383 * determined at assembly save time.
6385 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6386 name = mono_string_to_utf8 (ab->name);
6387 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6388 if (!mono_error_ok (&error)) {
6390 mono_error_raise_exception (&error);
6392 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6394 moduleb->module.image = &image->image;
6395 moduleb->dynamic_image = image;
6396 register_module (mono_object_domain (moduleb), moduleb, image);
6398 /* register the module with the assembly */
6399 ass = ab->dynamic_assembly->assembly.image;
6400 module_count = ass->module_count;
6401 new_modules = g_new0 (MonoImage *, module_count + 1);
6404 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6405 new_modules [module_count] = &image->image;
6406 mono_image_addref (&image->image);
6408 g_free (ass->modules);
6409 ass->modules = new_modules;
6410 ass->module_count ++;
6415 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6417 MonoDynamicImage *image = moduleb->dynamic_image;
6419 g_assert (type->type);
6420 image->wrappers_type = mono_class_from_mono_type (type->type);
6426 * mono_assembly_get_object:
6427 * @domain: an app domain
6428 * @assembly: an assembly
6430 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6432 MonoReflectionAssembly*
6433 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6435 static MonoClass *assembly_type;
6436 MonoReflectionAssembly *res;
6438 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6439 if (!assembly_type) {
6440 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6442 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6444 assembly_type = class;
6446 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6447 res->assembly = assembly;
6449 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6454 MonoReflectionModule*
6455 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6457 static MonoClass *module_type;
6458 MonoReflectionModule *res;
6461 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6463 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6465 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6467 module_type = class;
6469 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6472 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6474 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6475 basename = g_path_get_basename (image->name);
6476 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6477 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6481 if (image->assembly->image == image) {
6482 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6486 if (image->assembly->image->modules) {
6487 for (i = 0; i < image->assembly->image->module_count; i++) {
6488 if (image->assembly->image->modules [i] == image)
6489 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6491 g_assert (res->token);
6495 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6498 MonoReflectionModule*
6499 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6501 static MonoClass *module_type;
6502 MonoReflectionModule *res;
6503 MonoTableInfo *table;
6504 guint32 cols [MONO_FILE_SIZE];
6506 guint32 i, name_idx;
6510 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6512 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6514 module_type = class;
6516 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6518 table = &image->tables [MONO_TABLE_FILE];
6519 g_assert (table_index < table->rows);
6520 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6523 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6524 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6526 /* Check whenever the row has a corresponding row in the moduleref table */
6527 table = &image->tables [MONO_TABLE_MODULEREF];
6528 for (i = 0; i < table->rows; ++i) {
6529 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6530 val = mono_metadata_string_heap (image, name_idx);
6531 if (strcmp (val, name) == 0)
6532 res->image = image->modules [i];
6535 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6536 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6537 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6538 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6539 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6545 verify_safe_for_managed_space (MonoType *type)
6547 switch (type->type) {
6549 case MONO_TYPE_ARRAY:
6550 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6552 return verify_safe_for_managed_space (type->data.type);
6553 case MONO_TYPE_SZARRAY:
6554 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6555 case MONO_TYPE_GENERICINST: {
6556 MonoGenericInst *inst = type->data.generic_class->inst;
6560 for (i = 0; i < inst->type_argc; ++i)
6561 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6567 case MONO_TYPE_MVAR:
6575 mono_type_normalize (MonoType *type)
6578 MonoGenericClass *gclass;
6579 MonoGenericInst *ginst;
6581 MonoGenericContainer *gcontainer;
6582 MonoType **argv = NULL;
6583 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6585 if (type->type != MONO_TYPE_GENERICINST)
6588 gclass = type->data.generic_class;
6589 ginst = gclass->context.class_inst;
6590 if (!ginst->is_open)
6593 gtd = gclass->container_class;
6594 gcontainer = gtd->generic_container;
6595 argv = g_newa (MonoType*, ginst->type_argc);
6597 for (i = 0; i < ginst->type_argc; ++i) {
6598 MonoType *t = ginst->type_argv [i], *norm;
6599 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6600 is_denorm_gtd = FALSE;
6601 norm = mono_type_normalize (t);
6604 requires_rebind = TRUE;
6608 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6610 if (requires_rebind) {
6611 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6612 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6618 * mono_type_get_object:
6619 * @domain: an app domain
6622 * Return an System.MonoType object representing the type @type.
6625 mono_type_get_object (MonoDomain *domain, MonoType *type)
6627 MonoType *norm_type;
6628 MonoReflectionType *res;
6629 MonoClass *klass = mono_class_from_mono_type (type);
6631 /*we must avoid using @type as it might have come
6632 * from a mono_metadata_type_dup and the caller
6633 * expects that is can be freed.
6634 * Using the right type from
6636 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6638 /* void is very common */
6639 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6640 return (MonoReflectionType*)domain->typeof_void;
6643 * If the vtable of the given class was already created, we can use
6644 * the MonoType from there and avoid all locking and hash table lookups.
6646 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6647 * that the resulting object is different.
6649 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6650 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6651 if (vtable && vtable->type)
6652 return vtable->type;
6655 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6656 mono_domain_lock (domain);
6657 if (!domain->type_hash)
6658 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6659 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6660 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6661 mono_domain_unlock (domain);
6662 mono_loader_unlock ();
6666 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6667 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6668 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6669 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6670 * artifact of how generics are encoded and should be transparent to managed code so we
6671 * need to weed out this diference when retrieving managed System.Type objects.
6673 norm_type = mono_type_normalize (type);
6674 if (norm_type != type) {
6675 res = mono_type_get_object (domain, norm_type);
6676 mono_g_hash_table_insert (domain->type_hash, type, res);
6677 mono_domain_unlock (domain);
6678 mono_loader_unlock ();
6682 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6683 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6686 if (!verify_safe_for_managed_space (type)) {
6687 mono_domain_unlock (domain);
6688 mono_loader_unlock ();
6689 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6692 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6693 gboolean is_type_done = TRUE;
6694 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6695 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6696 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6698 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6699 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6701 if (gparam->owner && gparam->owner->is_method) {
6702 MonoMethod *method = gparam->owner->owner.method;
6703 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6704 is_type_done = FALSE;
6705 } else if (gparam->owner && !gparam->owner->is_method) {
6706 MonoClass *klass = gparam->owner->owner.klass;
6707 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6708 is_type_done = FALSE;
6712 /* g_assert_not_reached (); */
6713 /* should this be considered an error condition? */
6714 if (is_type_done && !type->byref) {
6715 mono_domain_unlock (domain);
6716 mono_loader_unlock ();
6717 return mono_class_get_ref_info (klass);
6720 /* This is stored in vtables/JITted code so it has to be pinned */
6721 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6723 mono_g_hash_table_insert (domain->type_hash, type, res);
6725 if (type->type == MONO_TYPE_VOID)
6726 domain->typeof_void = (MonoObject*)res;
6728 mono_domain_unlock (domain);
6729 mono_loader_unlock ();
6734 * mono_method_get_object:
6735 * @domain: an app domain
6737 * @refclass: the reflected type (can be NULL)
6739 * Return an System.Reflection.MonoMethod object representing the method @method.
6741 MonoReflectionMethod*
6742 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6745 * We use the same C representation for methods and constructors, but the type
6746 * name in C# is different.
6748 static MonoClass *System_Reflection_MonoMethod = NULL;
6749 static MonoClass *System_Reflection_MonoCMethod = NULL;
6750 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6751 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6753 MonoReflectionMethod *ret;
6755 if (method->is_inflated) {
6756 MonoReflectionGenericMethod *gret;
6758 refclass = method->klass;
6759 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6760 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6761 if (!System_Reflection_MonoGenericCMethod)
6762 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6763 klass = System_Reflection_MonoGenericCMethod;
6765 if (!System_Reflection_MonoGenericMethod)
6766 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6767 klass = System_Reflection_MonoGenericMethod;
6769 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6770 gret->method.method = method;
6771 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6772 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6773 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6777 refclass = method->klass;
6779 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6780 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6781 if (!System_Reflection_MonoCMethod)
6782 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6783 klass = System_Reflection_MonoCMethod;
6786 if (!System_Reflection_MonoMethod)
6787 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6788 klass = System_Reflection_MonoMethod;
6790 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6791 ret->method = method;
6792 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6793 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6797 * mono_method_clear_object:
6799 * Clear the cached reflection objects for the dynamic method METHOD.
6802 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6805 g_assert (method_is_dynamic (method));
6807 klass = method->klass;
6809 clear_cached_object (domain, method, klass);
6810 klass = klass->parent;
6812 /* Added by mono_param_get_objects () */
6813 clear_cached_object (domain, &(method->signature), NULL);
6814 klass = method->klass;
6816 clear_cached_object (domain, &(method->signature), klass);
6817 klass = klass->parent;
6822 * mono_field_get_object:
6823 * @domain: an app domain
6827 * Return an System.Reflection.MonoField object representing the field @field
6830 MonoReflectionField*
6831 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6833 MonoReflectionField *res;
6834 static MonoClass *monofield_klass;
6836 CHECK_OBJECT (MonoReflectionField *, field, klass);
6837 if (!monofield_klass)
6838 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6839 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6842 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6844 if (is_field_on_inst (field)) {
6845 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6846 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6849 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6850 res->attrs = mono_field_get_flags (field);
6852 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6856 * mono_property_get_object:
6857 * @domain: an app domain
6859 * @property: a property
6861 * Return an System.Reflection.MonoProperty object representing the property @property
6864 MonoReflectionProperty*
6865 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6867 MonoReflectionProperty *res;
6868 static MonoClass *monoproperty_klass;
6870 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6871 if (!monoproperty_klass)
6872 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6873 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6875 res->property = property;
6876 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6880 * mono_event_get_object:
6881 * @domain: an app domain
6885 * Return an System.Reflection.MonoEvent object representing the event @event
6888 MonoReflectionEvent*
6889 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6891 MonoReflectionEvent *res;
6892 MonoReflectionMonoEvent *mono_event;
6893 static MonoClass *monoevent_klass;
6895 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6896 if (!monoevent_klass)
6897 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6898 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6899 mono_event->klass = klass;
6900 mono_event->event = event;
6901 res = (MonoReflectionEvent*)mono_event;
6902 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6906 * mono_get_reflection_missing_object:
6907 * @domain: Domain where the object lives
6909 * Returns the System.Reflection.Missing.Value singleton object
6910 * (of type System.Reflection.Missing).
6912 * Used as the value for ParameterInfo.DefaultValue when Optional
6916 mono_get_reflection_missing_object (MonoDomain *domain)
6919 static MonoClassField *missing_value_field = NULL;
6921 if (!missing_value_field) {
6922 MonoClass *missing_klass;
6923 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6924 mono_class_init (missing_klass);
6925 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6926 g_assert (missing_value_field);
6928 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6934 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6937 *dbnull = mono_get_dbnull_object (domain);
6942 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6944 if (!*reflection_missing)
6945 *reflection_missing = mono_get_reflection_missing_object (domain);
6946 return *reflection_missing;
6950 * mono_param_get_objects:
6951 * @domain: an app domain
6954 * Return an System.Reflection.ParameterInfo array object representing the parameters
6955 * in the method @method.
6958 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6960 static MonoClass *System_Reflection_ParameterInfo;
6961 static MonoClass *System_Reflection_ParameterInfo_array;
6963 MonoArray *res = NULL;
6964 MonoReflectionMethod *member = NULL;
6965 MonoReflectionParameter *param = NULL;
6966 char **names, **blobs = NULL;
6967 guint32 *types = NULL;
6968 MonoType *type = NULL;
6969 MonoObject *dbnull = NULL;
6970 MonoObject *missing = NULL;
6971 MonoMarshalSpec **mspecs;
6972 MonoMethodSignature *sig;
6973 MonoVTable *pinfo_vtable;
6976 if (!System_Reflection_ParameterInfo_array) {
6979 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6981 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6983 mono_memory_barrier ();
6984 System_Reflection_ParameterInfo = klass;
6987 klass = mono_array_class_get (klass, 1);
6988 mono_memory_barrier ();
6989 System_Reflection_ParameterInfo_array = klass;
6992 sig = mono_method_signature_checked (method, &error);
6993 if (!mono_error_ok (&error))
6994 mono_error_raise_exception (&error);
6996 if (!sig->param_count)
6997 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6999 /* Note: the cache is based on the address of the signature into the method
7000 * since we already cache MethodInfos with the method as keys.
7002 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7004 member = mono_method_get_object (domain, method, refclass);
7005 names = g_new (char *, sig->param_count);
7006 mono_method_get_param_names (method, (const char **) names);
7008 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7009 mono_method_get_marshal_info (method, mspecs);
7011 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7012 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7013 for (i = 0; i < sig->param_count; ++i) {
7014 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7015 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7016 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7017 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7018 param->PositionImpl = i;
7019 param->AttrsImpl = sig->params [i]->attrs;
7021 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7022 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7023 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7025 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7029 blobs = g_new0 (char *, sig->param_count);
7030 types = g_new0 (guint32, sig->param_count);
7031 get_default_param_value_blobs (method, blobs, types);
7034 /* Build MonoType for the type from the Constant Table */
7036 type = g_new0 (MonoType, 1);
7037 type->type = types [i];
7038 type->data.klass = NULL;
7039 if (types [i] == MONO_TYPE_CLASS)
7040 type->data.klass = mono_defaults.object_class;
7041 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7042 /* For enums, types [i] contains the base type */
7044 type->type = MONO_TYPE_VALUETYPE;
7045 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7047 type->data.klass = mono_class_from_mono_type (type);
7049 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7051 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7052 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7053 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7054 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7056 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7062 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7064 mono_array_setref (res, i, param);
7071 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7073 mono_metadata_free_marshal_spec (mspecs [i]);
7076 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7080 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7082 return mono_param_get_objects_internal (domain, method, NULL);
7086 * mono_method_body_get_object:
7087 * @domain: an app domain
7090 * Return an System.Reflection.MethodBody object representing the method @method.
7092 MonoReflectionMethodBody*
7093 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7095 static MonoClass *System_Reflection_MethodBody = NULL;
7096 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7097 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7098 MonoReflectionMethodBody *ret;
7099 MonoMethodHeader *header;
7101 guint32 method_rva, local_var_sig_token;
7103 unsigned char format, flags;
7106 /* for compatibility with .net */
7107 if (method_is_dynamic (method))
7108 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7110 if (!System_Reflection_MethodBody)
7111 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7112 if (!System_Reflection_LocalVariableInfo)
7113 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7114 if (!System_Reflection_ExceptionHandlingClause)
7115 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7117 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7119 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7120 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7121 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7122 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7125 image = method->klass->image;
7126 header = mono_method_get_header (method);
7128 if (!image_is_dynamic (image)) {
7129 /* Obtain local vars signature token */
7130 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7131 ptr = mono_image_rva_map (image, method_rva);
7132 flags = *(const unsigned char *) ptr;
7133 format = flags & METHOD_HEADER_FORMAT_MASK;
7135 case METHOD_HEADER_TINY_FORMAT:
7136 local_var_sig_token = 0;
7138 case METHOD_HEADER_FAT_FORMAT:
7142 local_var_sig_token = read32 (ptr);
7145 g_assert_not_reached ();
7148 local_var_sig_token = 0; //FIXME
7150 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7152 ret->init_locals = header->init_locals;
7153 ret->max_stack = header->max_stack;
7154 ret->local_var_sig_token = local_var_sig_token;
7155 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7156 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7159 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7160 for (i = 0; i < header->num_locals; ++i) {
7161 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7162 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7163 info->is_pinned = header->locals [i]->pinned;
7164 info->local_index = i;
7165 mono_array_setref (ret->locals, i, info);
7169 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7170 for (i = 0; i < header->num_clauses; ++i) {
7171 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7172 MonoExceptionClause *clause = &header->clauses [i];
7174 info->flags = clause->flags;
7175 info->try_offset = clause->try_offset;
7176 info->try_length = clause->try_len;
7177 info->handler_offset = clause->handler_offset;
7178 info->handler_length = clause->handler_len;
7179 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7180 info->filter_offset = clause->data.filter_offset;
7181 else if (clause->data.catch_class)
7182 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7184 mono_array_setref (ret->clauses, i, info);
7187 mono_metadata_free_mh (header);
7188 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7193 * mono_get_dbnull_object:
7194 * @domain: Domain where the object lives
7196 * Returns the System.DBNull.Value singleton object
7198 * Used as the value for ParameterInfo.DefaultValue
7201 mono_get_dbnull_object (MonoDomain *domain)
7204 static MonoClassField *dbnull_value_field = NULL;
7206 if (!dbnull_value_field) {
7207 MonoClass *dbnull_klass;
7208 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7209 mono_class_init (dbnull_klass);
7210 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7211 g_assert (dbnull_value_field);
7213 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7219 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7221 guint32 param_index, i, lastp, crow = 0;
7222 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7225 MonoClass *klass = method->klass;
7226 MonoImage *image = klass->image;
7227 MonoMethodSignature *methodsig = mono_method_signature (method);
7229 MonoTableInfo *constt;
7230 MonoTableInfo *methodt;
7231 MonoTableInfo *paramt;
7233 if (!methodsig->param_count)
7236 mono_class_init (klass);
7238 if (image_is_dynamic (klass->image)) {
7239 MonoReflectionMethodAux *aux;
7240 if (method->is_inflated)
7241 method = ((MonoMethodInflated*)method)->declaring;
7242 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7243 if (aux && aux->param_defaults) {
7244 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7245 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7250 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7251 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7252 constt = &image->tables [MONO_TABLE_CONSTANT];
7254 idx = mono_method_get_index (method) - 1;
7255 g_assert (idx != -1);
7257 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7258 if (idx + 1 < methodt->rows)
7259 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7261 lastp = paramt->rows + 1;
7263 for (i = param_index; i < lastp; ++i) {
7266 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7267 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7269 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7272 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7277 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7278 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7279 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7286 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7291 MonoType *basetype = type;
7296 klass = mono_class_from_mono_type (type);
7297 if (klass->valuetype) {
7298 object = mono_object_new (domain, klass);
7299 retval = ((gchar *) object + sizeof (MonoObject));
7300 if (klass->enumtype)
7301 basetype = mono_class_enum_basetype (klass);
7306 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7313 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7316 gboolean quoted = FALSE;
7318 memset (assembly, 0, sizeof (MonoAssemblyName));
7319 assembly->culture = "";
7320 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7327 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7338 /* Remove trailing whitespace */
7340 while (*s && g_ascii_isspace (*s))
7343 while (g_ascii_isspace (*p))
7346 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7348 assembly->major = strtoul (p, &s, 10);
7349 if (s == p || *s != '.')
7352 assembly->minor = strtoul (p, &s, 10);
7353 if (s == p || *s != '.')
7356 assembly->build = strtoul (p, &s, 10);
7357 if (s == p || *s != '.')
7360 assembly->revision = strtoul (p, &s, 10);
7364 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7366 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7367 assembly->culture = "";
7370 assembly->culture = p;
7371 while (*p && *p != ',') {
7375 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7377 if (strncmp (p, "null", 4) == 0) {
7382 while (*p && *p != ',') {
7385 len = (p - start + 1);
7386 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7387 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7388 g_strlcpy ((char*)assembly->public_key_token, start, len);
7391 while (*p && *p != ',')
7395 while (g_ascii_isspace (*p) || *p == ',') {
7409 * mono_reflection_parse_type:
7412 * Parse a type name as accepted by the GetType () method and output the info
7413 * extracted in the info structure.
7414 * the name param will be mangled, so, make a copy before passing it to this function.
7415 * The fields in info will be valid until the memory pointed to by name is valid.
7417 * See also mono_type_get_name () below.
7419 * Returns: 0 on parse error.
7422 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7423 MonoTypeNameParse *info)
7425 char *start, *p, *w, *last_point, *startn;
7426 int in_modifiers = 0;
7427 int isbyref = 0, rank = 0;
7429 start = p = w = name;
7431 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7432 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7433 info->name = info->name_space = NULL;
7434 info->nested = NULL;
7435 info->modifiers = NULL;
7436 info->type_arguments = NULL;
7438 /* last_point separates the namespace from the name */
7441 while (*p == ' ') p++, start++, w++, name++;
7446 *p = 0; /* NULL terminate the name */
7448 info->nested = g_list_append (info->nested, startn);
7449 /* we have parsed the nesting namespace + name */
7453 info->name_space = start;
7455 info->name = last_point + 1;
7457 info->name_space = (char *)"";
7485 info->name_space = start;
7487 info->name = last_point + 1;
7489 info->name_space = (char *)"";
7496 if (isbyref) /* only one level allowed by the spec */
7499 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7503 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7507 //Decide if it's an array of a generic argument list
7512 if (*p == ',' || *p == '*' || *p == ']') { //array
7519 else if (*p == '*') /* '*' means unknown lower bound */
7520 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7527 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7529 if (rank) /* generic args after array spec*/ //XXX test
7531 info->type_arguments = g_ptr_array_new ();
7533 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7534 gboolean fqname = FALSE;
7536 g_ptr_array_add (info->type_arguments, subinfo);
7538 while (*p == ' ') p++;
7544 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7547 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7548 if (fqname && (*p != ']')) {
7556 while (*p && (*p != ']'))
7564 if (g_ascii_isspace (*aname)) {
7571 !assembly_name_to_aname (&subinfo->assembly, aname))
7573 } else if (fqname && (*p == ']')) {
7595 if (g_ascii_isspace (*p)) {
7602 return 0; /* missing assembly name */
7603 if (!assembly_name_to_aname (&info->assembly, p))
7609 if (info->assembly.name)
7612 // *w = 0; /* terminate class name */
7614 if (!info->name || !*info->name)
7618 /* add other consistency checks */
7623 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7625 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7629 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7631 gboolean type_resolve = FALSE;
7633 MonoImage *rootimage = image;
7635 if (info->assembly.name) {
7636 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7637 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7639 * This could happen in the AOT compiler case when the search hook is not
7642 assembly = image->assembly;
7644 /* then we must load the assembly ourselve - see #60439 */
7645 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7649 image = assembly->image;
7650 } else if (!image) {
7651 image = mono_defaults.corlib;
7654 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7655 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7656 image = mono_defaults.corlib;
7657 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7664 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7669 gboolean bounded = FALSE;
7672 image = mono_defaults.corlib;
7675 rootimage = mono_defaults.corlib;
7679 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7680 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7682 klass = mono_class_from_name (image, info->name_space, info->name);
7686 for (mod = info->nested; mod; mod = mod->next) {
7687 gpointer iter = NULL;
7691 mono_class_init (parent);
7693 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7695 char *nested_name, *nested_nspace;
7696 gboolean match = TRUE;
7698 lastp = strrchr (mod->data, '.');
7700 /* Nested classes can have namespaces */
7703 nested_name = g_strdup (lastp + 1);
7704 nspace_len = lastp - (char*)mod->data;
7705 nested_nspace = g_malloc (nspace_len + 1);
7706 memcpy (nested_nspace, mod->data, nspace_len);
7707 nested_nspace [nspace_len] = '\0';
7710 nested_name = mod->data;
7711 nested_nspace = NULL;
7714 if (nested_nspace) {
7716 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7719 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7725 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7728 if (strcmp (klass->name, nested_name) != 0)
7733 g_free (nested_name);
7734 g_free (nested_nspace);
7746 if (info->type_arguments) {
7747 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7748 MonoReflectionType *the_type;
7752 for (i = 0; i < info->type_arguments->len; i++) {
7753 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7755 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7756 if (!type_args [i]) {
7762 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7764 instance = mono_reflection_bind_generic_parameters (
7765 the_type, info->type_arguments->len, type_args);
7771 klass = mono_class_from_mono_type (instance);
7774 for (mod = info->modifiers; mod; mod = mod->next) {
7775 modval = GPOINTER_TO_UINT (mod->data);
7776 if (!modval) { /* byref: must be last modifier */
7777 return &klass->this_arg;
7778 } else if (modval == -1) {
7779 klass = mono_ptr_class_get (&klass->byval_arg);
7780 } else if (modval == -2) {
7782 } else { /* array rank */
7783 klass = mono_bounded_array_class_get (klass, modval, bounded);
7787 return &klass->byval_arg;
7791 * mono_reflection_get_type:
7792 * @image: a metadata context
7793 * @info: type description structure
7794 * @ignorecase: flag for case-insensitive string compares
7795 * @type_resolve: whenever type resolve was already tried
7797 * Build a MonoType from the type description in @info.
7802 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7803 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7807 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7809 MonoReflectionAssemblyBuilder *abuilder;
7813 g_assert (assembly_is_dynamic (assembly));
7814 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7816 /* Enumerate all modules */
7819 if (abuilder->modules) {
7820 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7821 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7822 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7828 if (!type && abuilder->loaded_modules) {
7829 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7830 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7831 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7841 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7844 MonoReflectionAssembly *assembly;
7848 if (image && image_is_dynamic (image))
7849 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7851 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7854 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7861 *type_resolve = TRUE;
7864 /* Reconstruct the type name */
7865 fullName = g_string_new ("");
7866 if (info->name_space && (info->name_space [0] != '\0'))
7867 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7869 g_string_printf (fullName, "%s", info->name);
7870 for (mod = info->nested; mod; mod = mod->next)
7871 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7873 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7875 if (assembly_is_dynamic (assembly->assembly))
7876 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7878 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7881 g_string_free (fullName, TRUE);
7886 mono_reflection_free_type_info (MonoTypeNameParse *info)
7888 g_list_free (info->modifiers);
7889 g_list_free (info->nested);
7891 if (info->type_arguments) {
7894 for (i = 0; i < info->type_arguments->len; i++) {
7895 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7897 mono_reflection_free_type_info (subinfo);
7898 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7902 g_ptr_array_free (info->type_arguments, TRUE);
7907 * mono_reflection_type_from_name:
7909 * @image: a metadata context (can be NULL).
7911 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7912 * it defaults to get the type from @image or, if @image is NULL or loading
7913 * from it fails, uses corlib.
7917 mono_reflection_type_from_name (char *name, MonoImage *image)
7919 MonoType *type = NULL;
7920 MonoTypeNameParse info;
7923 /* Make a copy since parse_type modifies its argument */
7924 tmp = g_strdup (name);
7926 /*g_print ("requested type %s\n", str);*/
7927 if (mono_reflection_parse_type (tmp, &info)) {
7928 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7932 mono_reflection_free_type_info (&info);
7937 * mono_reflection_get_token:
7939 * Return the metadata token of OBJ which should be an object
7940 * representing a metadata element.
7943 mono_reflection_get_token (MonoObject *obj)
7948 klass = obj->vtable->klass;
7950 if (strcmp (klass->name, "MethodBuilder") == 0) {
7951 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7953 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7954 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7955 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7957 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7958 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7959 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7961 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7962 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7963 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7964 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7965 } else if (strcmp (klass->name, "MonoType") == 0) {
7966 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7967 MonoClass *mc = mono_class_from_mono_type (type);
7968 if (!mono_class_init (mc))
7969 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7971 token = mc->type_token;
7972 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7973 strcmp (klass->name, "MonoMethod") == 0 ||
7974 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7975 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7976 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7977 if (m->method->is_inflated) {
7978 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7979 return inflated->declaring->token;
7981 token = m->method->token;
7983 } else if (strcmp (klass->name, "MonoField") == 0) {
7984 MonoReflectionField *f = (MonoReflectionField*)obj;
7986 if (is_field_on_inst (f->field)) {
7987 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7989 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7990 int field_index = f->field - dgclass->fields;
7993 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7994 obj = dgclass->field_objects [field_index];
7995 return mono_reflection_get_token (obj);
7998 token = mono_class_get_field_token (f->field);
7999 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8000 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8002 token = mono_class_get_property_token (p->property);
8003 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8004 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8006 token = mono_class_get_event_token (p->event);
8007 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8008 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8009 MonoClass *member_class = mono_object_class (p->MemberImpl);
8010 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8012 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8013 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8014 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8017 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8018 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8020 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8021 MonoException *ex = mono_get_exception_not_implemented (msg);
8023 mono_raise_exception (ex);
8030 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8034 int slen = mono_metadata_decode_value (p, &p);
8036 mono_error_init (error);
8038 n = g_memdup (p, slen + 1);
8040 t = mono_reflection_type_from_name (n, image);
8042 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8043 /* We don't free n, it's consumed by mono_error */
8044 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8050 return mono_class_from_mono_type (t);
8054 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8056 int slen, type = t->type;
8057 MonoClass *tklass = t->data.klass;
8059 mono_error_init (error);
8065 case MONO_TYPE_BOOLEAN: {
8066 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8071 case MONO_TYPE_CHAR:
8073 case MONO_TYPE_I2: {
8074 guint16 *val = g_malloc (sizeof (guint16));
8079 #if SIZEOF_VOID_P == 4
8085 case MONO_TYPE_I4: {
8086 guint32 *val = g_malloc (sizeof (guint32));
8091 #if SIZEOF_VOID_P == 8
8092 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8096 case MONO_TYPE_I8: {
8097 guint64 *val = g_malloc (sizeof (guint64));
8102 case MONO_TYPE_R8: {
8103 double *val = g_malloc (sizeof (double));
8108 case MONO_TYPE_VALUETYPE:
8109 if (t->data.klass->enumtype) {
8110 type = mono_class_enum_basetype (t->data.klass)->type;
8113 MonoClass *k = t->data.klass;
8115 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8116 guint64 *val = g_malloc (sizeof (guint64));
8122 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8125 case MONO_TYPE_STRING:
8126 if (*p == (char)0xFF) {
8130 slen = mono_metadata_decode_value (p, &p);
8132 return mono_string_new_len (mono_domain_get (), p, slen);
8133 case MONO_TYPE_CLASS: {
8136 if (*p == (char)0xFF) {
8141 slen = mono_metadata_decode_value (p, &p);
8142 n = g_memdup (p, slen + 1);
8144 t = mono_reflection_type_from_name (n, image);
8146 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8147 /* We don't free n, it's consumed by mono_error */
8148 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8153 return mono_type_get_object (mono_domain_get (), t);
8155 case MONO_TYPE_OBJECT: {
8158 MonoClass *subc = NULL;
8163 } else if (subt == 0x0E) {
8164 type = MONO_TYPE_STRING;
8166 } else if (subt == 0x1D) {
8167 MonoType simple_type = {{0}};
8171 type = MONO_TYPE_SZARRAY;
8172 if (etype == 0x50) {
8173 tklass = mono_defaults.systemtype_class;
8174 } else if (etype == 0x55) {
8175 tklass = load_cattr_enum_type (image, p, &p, error);
8176 if (!mono_error_ok (error))
8180 /* See Partition II, Appendix B3 */
8181 etype = MONO_TYPE_OBJECT;
8182 simple_type.type = etype;
8183 tklass = mono_class_from_mono_type (&simple_type);
8186 } else if (subt == 0x55) {
8189 slen = mono_metadata_decode_value (p, &p);
8190 n = g_memdup (p, slen + 1);
8192 t = mono_reflection_type_from_name (n, image);
8194 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8195 /* We don't free n, it's consumed by mono_error */
8196 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8201 subc = mono_class_from_mono_type (t);
8202 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8203 MonoType simple_type = {{0}};
8204 simple_type.type = subt;
8205 subc = mono_class_from_mono_type (&simple_type);
8207 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8209 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8211 if (mono_error_ok (error)) {
8212 obj = mono_object_new (mono_domain_get (), subc);
8213 g_assert (!subc->has_references);
8214 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8220 case MONO_TYPE_SZARRAY: {
8222 guint32 i, alen, basetype;
8225 if (alen == 0xffffffff) {
8229 arr = mono_array_new (mono_domain_get(), tklass, alen);
8230 basetype = tklass->byval_arg.type;
8231 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8232 basetype = mono_class_enum_basetype (tklass)->type;
8237 case MONO_TYPE_BOOLEAN:
8238 for (i = 0; i < alen; i++) {
8239 MonoBoolean val = *p++;
8240 mono_array_set (arr, MonoBoolean, i, val);
8243 case MONO_TYPE_CHAR:
8246 for (i = 0; i < alen; i++) {
8247 guint16 val = read16 (p);
8248 mono_array_set (arr, guint16, i, val);
8255 for (i = 0; i < alen; i++) {
8256 guint32 val = read32 (p);
8257 mono_array_set (arr, guint32, i, val);
8262 for (i = 0; i < alen; i++) {
8265 mono_array_set (arr, double, i, val);
8271 for (i = 0; i < alen; i++) {
8272 guint64 val = read64 (p);
8273 mono_array_set (arr, guint64, i, val);
8277 case MONO_TYPE_CLASS:
8278 case MONO_TYPE_OBJECT:
8279 case MONO_TYPE_STRING:
8280 case MONO_TYPE_SZARRAY:
8281 for (i = 0; i < alen; i++) {
8282 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8283 if (!mono_error_ok (error))
8285 mono_array_setref (arr, i, item);
8289 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8295 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8301 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8303 static MonoClass *klass;
8304 static MonoMethod *ctor;
8306 void *params [2], *unboxed;
8309 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8311 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8313 params [0] = mono_type_get_object (mono_domain_get (), t);
8315 retval = mono_object_new (mono_domain_get (), klass);
8316 unboxed = mono_object_unbox (retval);
8317 mono_runtime_invoke (ctor, unboxed, params, NULL);
8323 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8325 static MonoClass *klass;
8326 static MonoMethod *ctor;
8328 void *unboxed, *params [2];
8331 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8333 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8336 params [1] = typedarg;
8337 retval = mono_object_new (mono_domain_get (), klass);
8338 unboxed = mono_object_unbox (retval);
8339 mono_runtime_invoke (ctor, unboxed, params, NULL);
8345 type_is_reference (MonoType *type)
8347 switch (type->type) {
8348 case MONO_TYPE_BOOLEAN:
8349 case MONO_TYPE_CHAR:
8362 case MONO_TYPE_VALUETYPE:
8370 free_param_data (MonoMethodSignature *sig, void **params) {
8372 for (i = 0; i < sig->param_count; ++i) {
8373 if (!type_is_reference (sig->params [i]))
8374 g_free (params [i]);
8379 * Find the field index in the metadata FieldDef table.
8382 find_field_index (MonoClass *klass, MonoClassField *field) {
8385 for (i = 0; i < klass->field.count; ++i) {
8386 if (field == &klass->fields [i])
8387 return klass->field.first + 1 + i;
8393 * Find the property index in the metadata Property table.
8396 find_property_index (MonoClass *klass, MonoProperty *property) {
8399 for (i = 0; i < klass->ext->property.count; ++i) {
8400 if (property == &klass->ext->properties [i])
8401 return klass->ext->property.first + 1 + i;
8407 * Find the event index in the metadata Event table.
8410 find_event_index (MonoClass *klass, MonoEvent *event) {
8413 for (i = 0; i < klass->ext->event.count; ++i) {
8414 if (event == &klass->ext->events [i])
8415 return klass->ext->event.first + 1 + i;
8421 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8423 const char *p = (const char*)data;
8425 guint32 i, j, num_named;
8427 void *params_buf [32];
8428 void **params = NULL;
8429 MonoMethodSignature *sig;
8430 MonoObject *exc = NULL;
8432 mono_error_init (error);
8434 mono_class_init (method->klass);
8436 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8437 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8442 attr = mono_object_new (mono_domain_get (), method->klass);
8443 mono_runtime_invoke (method, attr, NULL, NULL);
8447 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8450 /*g_print ("got attr %s\n", method->klass->name);*/
8452 sig = mono_method_signature (method);
8453 if (sig->param_count < 32) {
8454 params = params_buf;
8455 memset (params, 0, sizeof (void*) * sig->param_count);
8457 /* Allocate using GC so it gets GC tracking */
8458 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8463 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8464 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8465 if (!mono_error_ok (error))
8470 attr = mono_object_new (mono_domain_get (), method->klass);
8472 mono_runtime_invoke (method, attr, params, &exc);
8475 num_named = read16 (named);
8477 for (j = 0; j < num_named; j++) {
8479 char *name, named_type, data_type;
8480 named_type = *named++;
8481 data_type = *named++; /* type of data */
8482 if (data_type == MONO_TYPE_SZARRAY)
8483 data_type = *named++;
8484 if (data_type == MONO_TYPE_ENUM) {
8487 type_len = mono_metadata_decode_blob_size (named, &named);
8488 type_name = g_malloc (type_len + 1);
8489 memcpy (type_name, named, type_len);
8490 type_name [type_len] = 0;
8492 /* FIXME: lookup the type and check type consistency */
8495 name_len = mono_metadata_decode_blob_size (named, &named);
8496 name = g_malloc (name_len + 1);
8497 memcpy (name, named, name_len);
8498 name [name_len] = 0;
8500 if (named_type == 0x53) {
8501 MonoClassField *field;
8504 /* how this fail is a blackbox */
8505 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8507 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8512 val = load_cattr_value (image, field->type, named, &named, error);
8513 if (!mono_error_ok (error)) {
8515 if (!type_is_reference (field->type))
8520 mono_field_set_value (attr, field, val);
8521 if (!type_is_reference (field->type))
8523 } else if (named_type == 0x54) {
8526 MonoType *prop_type;
8528 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8531 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8537 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8542 /* can we have more that 1 arg in a custom attr named property? */
8543 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8544 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8546 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8547 if (!mono_error_ok (error)) {
8549 if (!type_is_reference (prop_type))
8550 g_free (pparams [0]);
8555 mono_property_set_value (prop, attr, pparams, NULL);
8556 if (!type_is_reference (prop_type))
8557 g_free (pparams [0]);
8562 free_param_data (method->signature, params);
8563 if (params != params_buf)
8564 mono_gc_free_fixed (params);
8569 free_param_data (method->signature, params);
8570 if (params != params_buf)
8571 mono_gc_free_fixed (params);
8573 mono_raise_exception ((MonoException*)exc);
8578 * mono_reflection_create_custom_attr_data_args:
8580 * Create an array of typed and named arguments from the cattr blob given by DATA.
8581 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8582 * NAMED_ARG_INFO will contain information about the named arguments.
8585 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)
8587 MonoArray *typedargs, *namedargs;
8588 MonoClass *attrklass;
8590 const char *p = (const char*)data;
8592 guint32 i, j, num_named;
8593 CattrNamedArg *arginfo = NULL;
8597 *named_arg_info = NULL;
8599 mono_error_init (error);
8601 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8602 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8606 mono_class_init (method->klass);
8608 domain = mono_domain_get ();
8610 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8613 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8617 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8621 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8622 if (!mono_error_ok (error)) {
8623 if (!type_is_reference (mono_method_signature (method)->params [i]))
8628 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8629 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8630 mono_array_setref (typedargs, i, obj);
8632 if (!type_is_reference (mono_method_signature (method)->params [i]))
8637 num_named = read16 (named);
8638 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8640 attrklass = method->klass;
8642 arginfo = g_new0 (CattrNamedArg, num_named);
8643 *named_arg_info = arginfo;
8645 for (j = 0; j < num_named; j++) {
8647 char *name, named_type, data_type;
8648 named_type = *named++;
8649 data_type = *named++; /* type of data */
8650 if (data_type == MONO_TYPE_SZARRAY)
8651 data_type = *named++;
8652 if (data_type == MONO_TYPE_ENUM) {
8655 type_len = mono_metadata_decode_blob_size (named, &named);
8656 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8659 type_name = g_malloc (type_len + 1);
8660 memcpy (type_name, named, type_len);
8661 type_name [type_len] = 0;
8663 /* FIXME: lookup the type and check type consistency */
8666 name_len = mono_metadata_decode_blob_size (named, &named);
8667 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8669 name = g_malloc (name_len + 1);
8670 memcpy (name, named, name_len);
8671 name [name_len] = 0;
8673 if (named_type == 0x53) {
8675 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8683 arginfo [j].type = field->type;
8684 arginfo [j].field = field;
8686 val = load_cattr_value (image, field->type, named, &named, error);
8687 if (!mono_error_ok (error)) {
8688 if (!type_is_reference (field->type))
8694 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8695 mono_array_setref (namedargs, j, obj);
8696 if (!type_is_reference (field->type))
8698 } else if (named_type == 0x54) {
8700 MonoType *prop_type;
8701 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8704 if (!prop || !prop->set) {
8709 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8710 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8712 arginfo [j].type = prop_type;
8713 arginfo [j].prop = prop;
8715 val = load_cattr_value (image, prop_type, named, &named, error);
8716 if (!mono_error_ok (error)) {
8717 if (!type_is_reference (prop_type))
8723 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8724 mono_array_setref (namedargs, j, obj);
8725 if (!type_is_reference (prop_type))
8731 *typed_args = typedargs;
8732 *named_args = namedargs;
8735 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8737 *named_arg_info = NULL;
8741 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8744 MonoArray *typedargs, *namedargs;
8747 CattrNamedArg *arginfo = NULL;
8757 image = assembly->assembly->image;
8758 method = ref_method->method;
8759 domain = mono_object_domain (ref_method);
8761 if (!mono_class_init (method->klass))
8762 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8764 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8765 if (!mono_error_ok (&error))
8766 mono_error_raise_exception (&error);
8767 if (mono_loader_get_last_error ())
8768 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8770 if (!typedargs || !namedargs) {
8775 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8776 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8777 MonoObject *typedarg;
8779 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8780 mono_array_setref (typedargs, i, typedarg);
8783 for (i = 0; i < mono_array_length (namedargs); ++i) {
8784 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8785 MonoObject *typedarg, *namedarg, *minfo;
8787 if (arginfo [i].prop)
8788 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8790 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8792 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8793 namedarg = create_cattr_named_arg (minfo, typedarg);
8795 mono_array_setref (namedargs, i, namedarg);
8798 *ctor_args = typedargs;
8799 *named_args = namedargs;
8804 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8806 static MonoMethod *ctor;
8811 g_assert (image->assembly);
8814 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8816 domain = mono_domain_get ();
8817 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8818 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8819 params [1] = mono_assembly_get_object (domain, image->assembly);
8820 params [2] = (gpointer)&cattr->data;
8821 params [3] = &cattr->data_size;
8822 mono_runtime_invoke (ctor, attr, params, NULL);
8827 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8833 mono_error_init (error);
8836 for (i = 0; i < cinfo->num_attrs; ++i) {
8837 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8841 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8843 for (i = 0; i < cinfo->num_attrs; ++i) {
8844 if (!cinfo->attrs [i].ctor)
8845 /* The cattr type is not finished yet */
8846 /* We should include the type name but cinfo doesn't contain it */
8847 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8848 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8849 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8850 if (!mono_error_ok (error))
8852 mono_array_setref (result, n, attr);
8860 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8863 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8864 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8870 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8876 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8877 for (i = 0; i < cinfo->num_attrs; ++i) {
8878 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8879 mono_array_setref (result, i, attr);
8885 * mono_custom_attrs_from_index:
8887 * Returns: NULL if no attributes are found or if a loading error occurs.
8890 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8892 guint32 mtoken, i, len;
8893 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8895 MonoCustomAttrInfo *ainfo;
8896 GList *tmp, *list = NULL;
8898 MonoCustomAttrEntry* attr;
8900 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8902 i = mono_metadata_custom_attrs_from_index (image, idx);
8906 while (i < ca->rows) {
8907 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8909 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8912 len = g_list_length (list);
8915 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8916 ainfo->num_attrs = len;
8917 ainfo->image = image;
8918 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8919 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8920 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8921 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8922 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8923 mtoken |= MONO_TOKEN_METHOD_DEF;
8925 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8926 mtoken |= MONO_TOKEN_MEMBER_REF;
8929 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8932 attr = &ainfo->attrs [i - 1];
8933 attr->ctor = mono_get_method (image, mtoken, NULL);
8935 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8941 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8942 /*FIXME raising an exception here doesn't make any sense*/
8943 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8948 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8949 attr->data_size = mono_metadata_decode_value (data, &data);
8950 attr->data = (guchar*)data;
8958 mono_custom_attrs_from_method (MonoMethod *method)
8963 * An instantiated method has the same cattrs as the generic method definition.
8965 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8966 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8968 if (method->is_inflated)
8969 method = ((MonoMethodInflated *) method)->declaring;
8971 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8972 return lookup_custom_attr (method->klass->image, method);
8975 /* Synthetic methods */
8978 idx = mono_method_get_index (method);
8979 idx <<= MONO_CUSTOM_ATTR_BITS;
8980 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8981 return mono_custom_attrs_from_index (method->klass->image, idx);
8985 mono_custom_attrs_from_class (MonoClass *klass)
8989 if (klass->generic_class)
8990 klass = klass->generic_class->container_class;
8992 if (image_is_dynamic (klass->image))
8993 return lookup_custom_attr (klass->image, klass);
8995 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8996 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8997 idx <<= MONO_CUSTOM_ATTR_BITS;
8998 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9000 idx = mono_metadata_token_index (klass->type_token);
9001 idx <<= MONO_CUSTOM_ATTR_BITS;
9002 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9004 return mono_custom_attrs_from_index (klass->image, idx);
9008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9012 if (image_is_dynamic (assembly->image))
9013 return lookup_custom_attr (assembly->image, assembly);
9014 idx = 1; /* there is only one assembly */
9015 idx <<= MONO_CUSTOM_ATTR_BITS;
9016 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9017 return mono_custom_attrs_from_index (assembly->image, idx);
9020 static MonoCustomAttrInfo*
9021 mono_custom_attrs_from_module (MonoImage *image)
9025 if (image_is_dynamic (image))
9026 return lookup_custom_attr (image, image);
9027 idx = 1; /* there is only one module */
9028 idx <<= MONO_CUSTOM_ATTR_BITS;
9029 idx |= MONO_CUSTOM_ATTR_MODULE;
9030 return mono_custom_attrs_from_index (image, idx);
9034 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9038 if (image_is_dynamic (klass->image)) {
9039 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9040 return lookup_custom_attr (klass->image, property);
9042 idx = find_property_index (klass, property);
9043 idx <<= MONO_CUSTOM_ATTR_BITS;
9044 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9045 return mono_custom_attrs_from_index (klass->image, idx);
9049 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9053 if (image_is_dynamic (klass->image)) {
9054 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9055 return lookup_custom_attr (klass->image, event);
9057 idx = find_event_index (klass, event);
9058 idx <<= MONO_CUSTOM_ATTR_BITS;
9059 idx |= MONO_CUSTOM_ATTR_EVENT;
9060 return mono_custom_attrs_from_index (klass->image, idx);
9064 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9067 if (image_is_dynamic (klass->image)) {
9068 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9069 return lookup_custom_attr (klass->image, field);
9071 idx = find_field_index (klass, field);
9072 idx <<= MONO_CUSTOM_ATTR_BITS;
9073 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9074 return mono_custom_attrs_from_index (klass->image, idx);
9078 * mono_custom_attrs_from_param:
9079 * @method: handle to the method that we want to retrieve custom parameter information from
9080 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9082 * The result must be released with mono_custom_attrs_free().
9084 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9087 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9090 guint32 i, idx, method_index;
9091 guint32 param_list, param_last, param_pos, found;
9093 MonoReflectionMethodAux *aux;
9096 * An instantiated method has the same cattrs as the generic method definition.
9098 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9099 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9101 if (method->is_inflated)
9102 method = ((MonoMethodInflated *) method)->declaring;
9104 if (image_is_dynamic (method->klass->image)) {
9105 MonoCustomAttrInfo *res, *ainfo;
9108 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9109 if (!aux || !aux->param_cattr)
9112 /* Need to copy since it will be freed later */
9113 ainfo = aux->param_cattr [param];
9116 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9117 res = g_malloc0 (size);
9118 memcpy (res, ainfo, size);
9122 image = method->klass->image;
9123 method_index = mono_method_get_index (method);
9126 ca = &image->tables [MONO_TABLE_METHOD];
9128 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9129 if (method_index == ca->rows) {
9130 ca = &image->tables [MONO_TABLE_PARAM];
9131 param_last = ca->rows + 1;
9133 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9134 ca = &image->tables [MONO_TABLE_PARAM];
9137 for (i = param_list; i < param_last; ++i) {
9138 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9139 if (param_pos == param) {
9147 idx <<= MONO_CUSTOM_ATTR_BITS;
9148 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9149 return mono_custom_attrs_from_index (image, idx);
9153 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9157 for (i = 0; i < ainfo->num_attrs; ++i) {
9158 klass = ainfo->attrs [i].ctor->klass;
9159 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9166 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9169 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9170 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9175 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9181 mono_error_init (error);
9184 for (i = 0; i < ainfo->num_attrs; ++i) {
9185 klass = ainfo->attrs [i].ctor->klass;
9186 if (mono_class_has_parent (klass, attr_klass)) {
9191 if (attr_index == -1)
9194 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9195 if (!mono_error_ok (error))
9197 return mono_array_get (attrs, MonoObject*, attr_index);
9201 * mono_reflection_get_custom_attrs_info:
9202 * @obj: a reflection object handle
9204 * Return the custom attribute info for attributes defined for the
9205 * reflection handle @obj. The objects.
9207 * FIXME this function leaks like a sieve for SRE objects.
9210 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9213 MonoCustomAttrInfo *cinfo = NULL;
9215 klass = obj->vtable->klass;
9216 if (klass == mono_defaults.monotype_class) {
9217 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9218 klass = mono_class_from_mono_type (type);
9219 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9220 cinfo = mono_custom_attrs_from_class (klass);
9221 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9222 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9223 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9224 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9225 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9226 cinfo = mono_custom_attrs_from_module (module->image);
9227 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9228 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9229 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9230 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9231 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9232 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9233 } else if (strcmp ("MonoField", klass->name) == 0) {
9234 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9235 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9236 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9237 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9238 cinfo = mono_custom_attrs_from_method (rmethod->method);
9239 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9240 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9241 cinfo = mono_custom_attrs_from_method (rmethod->method);
9242 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9243 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9244 MonoClass *member_class = mono_object_class (param->MemberImpl);
9245 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9246 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9247 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9248 } else if (is_sr_mono_property (member_class)) {
9249 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9251 if (!(method = prop->property->get))
9252 method = prop->property->set;
9255 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9257 #ifndef DISABLE_REFLECTION_EMIT
9258 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9259 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9260 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9261 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9262 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9263 MonoMethod *method = NULL;
9264 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9265 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9266 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9267 method = ((MonoReflectionMethod *)c->cb)->method;
9269 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));
9271 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9275 char *type_name = mono_type_get_full_name (member_class);
9276 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9277 MonoException *ex = mono_get_exception_not_supported (msg);
9280 mono_raise_exception (ex);
9282 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9283 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9284 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9285 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9286 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9287 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9288 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9289 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9290 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9291 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9292 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9293 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9294 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9295 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9296 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9297 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9298 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9299 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9300 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9301 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9302 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9303 } else { /* handle other types here... */
9304 g_error ("get custom attrs not yet supported for %s", klass->name);
9311 * mono_reflection_get_custom_attrs_by_type:
9312 * @obj: a reflection object handle
9314 * Return an array with all the custom attributes defined of the
9315 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9316 * of that type are returned. The objects are fully build. Return NULL if a loading error
9320 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9323 MonoCustomAttrInfo *cinfo;
9325 mono_error_init (error);
9327 cinfo = mono_reflection_get_custom_attrs_info (obj);
9329 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9331 mono_custom_attrs_free (cinfo);
9333 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9334 if (mono_loader_get_last_error ())
9336 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9343 * mono_reflection_get_custom_attrs:
9344 * @obj: a reflection object handle
9346 * Return an array with all the custom attributes defined of the
9347 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9351 mono_reflection_get_custom_attrs (MonoObject *obj)
9355 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9359 * mono_reflection_get_custom_attrs_data:
9360 * @obj: a reflection obj handle
9362 * Returns an array of System.Reflection.CustomAttributeData,
9363 * which include information about attributes reflected on
9364 * types loaded using the Reflection Only methods
9367 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9370 MonoCustomAttrInfo *cinfo;
9372 cinfo = mono_reflection_get_custom_attrs_info (obj);
9374 result = mono_custom_attrs_data_construct (cinfo);
9376 mono_custom_attrs_free (cinfo);
9378 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9383 static MonoReflectionType*
9384 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9386 static MonoMethod *method_get_underlying_system_type = NULL;
9387 MonoMethod *usertype_method;
9389 if (!method_get_underlying_system_type)
9390 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9391 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9392 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9397 is_corlib_type (MonoClass *class)
9399 return class->image == mono_defaults.corlib;
9402 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9403 static MonoClass *cached_class; \
9405 return cached_class == _class; \
9406 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9407 cached_class = _class; \
9414 #ifndef DISABLE_REFLECTION_EMIT
9416 is_sre_array (MonoClass *class)
9418 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9422 is_sre_byref (MonoClass *class)
9424 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9428 is_sre_pointer (MonoClass *class)
9430 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9434 is_sre_generic_instance (MonoClass *class)
9436 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9440 is_sre_type_builder (MonoClass *class)
9442 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9446 is_sre_method_builder (MonoClass *class)
9448 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9452 is_sre_ctor_builder (MonoClass *class)
9454 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9458 is_sre_field_builder (MonoClass *class)
9460 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9464 is_sre_method_on_tb_inst (MonoClass *class)
9466 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9470 is_sre_ctor_on_tb_inst (MonoClass *class)
9472 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9476 mono_reflection_type_get_handle (MonoReflectionType* ref)
9484 if (is_usertype (ref)) {
9485 ref = mono_reflection_type_get_underlying_system_type (ref);
9486 if (ref == NULL || is_usertype (ref))
9492 class = mono_object_class (ref);
9494 if (is_sre_array (class)) {
9496 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9497 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9499 if (sre_array->rank == 0) //single dimentional array
9500 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9502 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9503 sre_array->type.type = res;
9505 } else if (is_sre_byref (class)) {
9507 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9508 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9510 res = &mono_class_from_mono_type (base)->this_arg;
9511 sre_byref->type.type = res;
9513 } else if (is_sre_pointer (class)) {
9515 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9516 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9518 res = &mono_ptr_class_get (base)->byval_arg;
9519 sre_pointer->type.type = res;
9521 } else if (is_sre_generic_instance (class)) {
9522 MonoType *res, **types;
9523 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9526 count = mono_array_length (gclass->type_arguments);
9527 types = g_new0 (MonoType*, count);
9528 for (i = 0; i < count; ++i) {
9529 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9530 types [i] = mono_reflection_type_get_handle (t);
9537 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9540 gclass->type.type = res;
9544 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9551 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9553 mono_reflection_type_get_handle (type);
9557 mono_reflection_register_with_runtime (MonoReflectionType *type)
9559 MonoType *res = mono_reflection_type_get_handle (type);
9560 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9564 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9566 class = mono_class_from_mono_type (res);
9568 mono_loader_lock (); /*same locking as mono_type_get_object*/
9569 mono_domain_lock (domain);
9571 if (!image_is_dynamic (class->image)) {
9572 mono_class_setup_supertypes (class);
9574 if (!domain->type_hash)
9575 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9576 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9577 mono_g_hash_table_insert (domain->type_hash, res, type);
9579 mono_domain_unlock (domain);
9580 mono_loader_unlock ();
9584 * LOCKING: Assumes the loader lock is held.
9586 static MonoMethodSignature*
9587 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9588 MonoMethodSignature *sig;
9591 count = parameters? mono_array_length (parameters): 0;
9593 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9594 sig->param_count = count;
9595 sig->sentinelpos = -1; /* FIXME */
9596 for (i = 0; i < count; ++i)
9597 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9602 * LOCKING: Assumes the loader lock is held.
9604 static MonoMethodSignature*
9605 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9606 MonoMethodSignature *sig;
9608 sig = parameters_to_signature (image, ctor->parameters);
9609 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9610 sig->ret = &mono_defaults.void_class->byval_arg;
9615 * LOCKING: Assumes the loader lock is held.
9617 static MonoMethodSignature*
9618 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9619 MonoMethodSignature *sig;
9621 sig = parameters_to_signature (image, method->parameters);
9622 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9623 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9624 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9628 static MonoMethodSignature*
9629 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9630 MonoMethodSignature *sig;
9632 sig = parameters_to_signature (NULL, method->parameters);
9633 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9634 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9635 sig->generic_param_count = 0;
9640 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9642 MonoClass *klass = mono_object_class (prop);
9643 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9644 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9645 *name = mono_string_to_utf8 (pb->name);
9646 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9648 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9649 *name = g_strdup (p->property->name);
9650 if (p->property->get)
9651 *type = mono_method_signature (p->property->get)->ret;
9653 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9658 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9660 MonoClass *klass = mono_object_class (field);
9661 if (strcmp (klass->name, "FieldBuilder") == 0) {
9662 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9663 *name = mono_string_to_utf8 (fb->name);
9664 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9666 MonoReflectionField *f = (MonoReflectionField *)field;
9667 *name = g_strdup (mono_field_get_name (f->field));
9668 *type = f->field->type;
9672 #else /* DISABLE_REFLECTION_EMIT */
9675 mono_reflection_register_with_runtime (MonoReflectionType *type)
9681 is_sre_type_builder (MonoClass *class)
9687 is_sre_generic_instance (MonoClass *class)
9693 init_type_builder_generics (MonoObject *type)
9697 #endif /* !DISABLE_REFLECTION_EMIT */
9701 is_sr_mono_field (MonoClass *class)
9703 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9707 is_sr_mono_property (MonoClass *class)
9709 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9713 is_sr_mono_method (MonoClass *class)
9715 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9719 is_sr_mono_cmethod (MonoClass *class)
9721 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9725 is_sr_mono_generic_method (MonoClass *class)
9727 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9731 is_sr_mono_generic_cmethod (MonoClass *class)
9733 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9737 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9739 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9743 is_usertype (MonoReflectionType *ref)
9745 MonoClass *class = mono_object_class (ref);
9746 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9749 static MonoReflectionType*
9750 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9752 if (!type || type->type)
9755 if (is_usertype (type)) {
9756 type = mono_reflection_type_get_underlying_system_type (type);
9757 if (is_usertype (type))
9758 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9764 * Encode a value in a custom attribute stream of bytes.
9765 * The value to encode is either supplied as an object in argument val
9766 * (valuetypes are boxed), or as a pointer to the data in the
9768 * @type represents the type of the value
9769 * @buffer is the start of the buffer
9770 * @p the current position in the buffer
9771 * @buflen contains the size of the buffer and is used to return the new buffer size
9772 * if this needs to be realloced.
9773 * @retbuffer and @retp return the start and the position of the buffer
9776 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9778 MonoTypeEnum simple_type;
9780 if ((p-buffer) + 10 >= *buflen) {
9783 newbuf = g_realloc (buffer, *buflen);
9784 p = newbuf + (p-buffer);
9788 argval = ((char*)arg + sizeof (MonoObject));
9789 simple_type = type->type;
9791 switch (simple_type) {
9792 case MONO_TYPE_BOOLEAN:
9797 case MONO_TYPE_CHAR:
9800 swap_with_size (p, argval, 2, 1);
9806 swap_with_size (p, argval, 4, 1);
9810 swap_with_size (p, argval, 8, 1);
9815 swap_with_size (p, argval, 8, 1);
9818 case MONO_TYPE_VALUETYPE:
9819 if (type->data.klass->enumtype) {
9820 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9823 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9826 case MONO_TYPE_STRING: {
9833 str = mono_string_to_utf8 ((MonoString*)arg);
9834 slen = strlen (str);
9835 if ((p-buffer) + 10 + slen >= *buflen) {
9839 newbuf = g_realloc (buffer, *buflen);
9840 p = newbuf + (p-buffer);
9843 mono_metadata_encode_value (slen, p, &p);
9844 memcpy (p, str, slen);
9849 case MONO_TYPE_CLASS: {
9857 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9858 slen = strlen (str);
9859 if ((p-buffer) + 10 + slen >= *buflen) {
9863 newbuf = g_realloc (buffer, *buflen);
9864 p = newbuf + (p-buffer);
9867 mono_metadata_encode_value (slen, p, &p);
9868 memcpy (p, str, slen);
9873 case MONO_TYPE_SZARRAY: {
9875 MonoClass *eclass, *arg_eclass;
9878 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9881 len = mono_array_length ((MonoArray*)arg);
9883 *p++ = (len >> 8) & 0xff;
9884 *p++ = (len >> 16) & 0xff;
9885 *p++ = (len >> 24) & 0xff;
9887 *retbuffer = buffer;
9888 eclass = type->data.klass;
9889 arg_eclass = mono_object_class (arg)->element_class;
9892 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9893 eclass = mono_defaults.object_class;
9895 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9896 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9897 int elsize = mono_class_array_element_size (arg_eclass);
9898 for (i = 0; i < len; ++i) {
9899 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9902 } else if (eclass->valuetype && arg_eclass->valuetype) {
9903 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9904 int elsize = mono_class_array_element_size (eclass);
9905 for (i = 0; i < len; ++i) {
9906 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9910 for (i = 0; i < len; ++i) {
9911 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9916 case MONO_TYPE_OBJECT: {
9922 * The parameter type is 'object' but the type of the actual
9923 * argument is not. So we have to add type information to the blob
9924 * too. This is completely undocumented in the spec.
9928 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9933 klass = mono_object_class (arg);
9935 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9938 } else if (klass->enumtype) {
9940 } else if (klass == mono_defaults.string_class) {
9941 simple_type = MONO_TYPE_STRING;
9944 } else if (klass->rank == 1) {
9946 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9947 /* See Partition II, Appendix B3 */
9950 *p++ = klass->element_class->byval_arg.type;
9951 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9953 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9954 *p++ = simple_type = klass->byval_arg.type;
9957 g_error ("unhandled type in custom attr");
9959 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9960 slen = strlen (str);
9961 if ((p-buffer) + 10 + slen >= *buflen) {
9965 newbuf = g_realloc (buffer, *buflen);
9966 p = newbuf + (p-buffer);
9969 mono_metadata_encode_value (slen, p, &p);
9970 memcpy (p, str, slen);
9973 simple_type = mono_class_enum_basetype (klass)->type;
9977 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9980 *retbuffer = buffer;
9984 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9986 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9987 char *str = type_get_qualified_name (type, NULL);
9988 int slen = strlen (str);
9992 * This seems to be optional...
9995 mono_metadata_encode_value (slen, p, &p);
9996 memcpy (p, str, slen);
9999 } else if (type->type == MONO_TYPE_OBJECT) {
10001 } else if (type->type == MONO_TYPE_CLASS) {
10002 /* it should be a type: encode_cattr_value () has the check */
10005 mono_metadata_encode_value (type->type, p, &p);
10006 if (type->type == MONO_TYPE_SZARRAY)
10007 /* See the examples in Partition VI, Annex B */
10008 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10014 #ifndef DISABLE_REFLECTION_EMIT
10016 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10019 /* Preallocate a large enough buffer */
10020 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10021 char *str = type_get_qualified_name (type, NULL);
10022 len = strlen (str);
10024 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10025 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10026 len = strlen (str);
10031 len += strlen (name);
10033 if ((p-buffer) + 20 + len >= *buflen) {
10037 newbuf = g_realloc (buffer, *buflen);
10038 p = newbuf + (p-buffer);
10042 encode_field_or_prop_type (type, p, &p);
10044 len = strlen (name);
10045 mono_metadata_encode_value (len, p, &p);
10046 memcpy (p, name, len);
10048 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10050 *retbuffer = buffer;
10054 * mono_reflection_get_custom_attrs_blob:
10055 * @ctor: custom attribute constructor
10056 * @ctorArgs: arguments o the constructor
10062 * Creates the blob of data that needs to be saved in the metadata and that represents
10063 * the custom attributed described by @ctor, @ctorArgs etc.
10064 * Returns: a Byte array representing the blob of data.
10067 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10070 MonoMethodSignature *sig;
10075 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10076 /* sig is freed later so allocate it in the heap */
10077 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10079 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10082 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10084 p = buffer = g_malloc (buflen);
10085 /* write the prolog */
10088 for (i = 0; i < sig->param_count; ++i) {
10089 arg = mono_array_get (ctorArgs, MonoObject*, i);
10090 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10094 i += mono_array_length (properties);
10096 i += mono_array_length (fields);
10098 *p++ = (i >> 8) & 0xff;
10101 for (i = 0; i < mono_array_length (properties); ++i) {
10105 prop = mono_array_get (properties, gpointer, i);
10106 get_prop_name_and_type (prop, &pname, &ptype);
10107 *p++ = 0x54; /* PROPERTY signature */
10108 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10115 for (i = 0; i < mono_array_length (fields); ++i) {
10119 field = mono_array_get (fields, gpointer, i);
10120 get_field_name_and_type (field, &fname, &ftype);
10121 *p++ = 0x53; /* FIELD signature */
10122 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10127 g_assert (p - buffer <= buflen);
10128 buflen = p - buffer;
10129 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10130 p = mono_array_addr (result, char, 0);
10131 memcpy (p, buffer, buflen);
10133 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10139 * mono_reflection_setup_internal_class:
10140 * @tb: a TypeBuilder object
10142 * Creates a MonoClass that represents the TypeBuilder.
10143 * This is a trick that lets us simplify a lot of reflection code
10144 * (and will allow us to support Build and Run assemblies easier).
10147 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10150 MonoClass *klass, *parent;
10152 RESOLVE_TYPE (tb->parent);
10154 mono_loader_lock ();
10157 /* check so we can compile corlib correctly */
10158 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10159 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10160 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10162 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10168 /* the type has already being created: it means we just have to change the parent */
10169 if (tb->type.type) {
10170 klass = mono_class_from_mono_type (tb->type.type);
10171 klass->parent = NULL;
10172 /* fool mono_class_setup_parent */
10173 klass->supertypes = NULL;
10174 mono_class_setup_parent (klass, parent);
10175 mono_class_setup_mono_type (klass);
10176 mono_loader_unlock ();
10180 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10182 klass->image = &tb->module->dynamic_image->image;
10184 klass->inited = 1; /* we lie to the runtime */
10185 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10186 if (!mono_error_ok (&error))
10188 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10189 if (!mono_error_ok (&error))
10191 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10192 klass->flags = tb->attrs;
10194 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10196 klass->element_class = klass;
10198 if (mono_class_get_ref_info (klass) == NULL) {
10200 mono_class_set_ref_info (klass, tb);
10202 /* Put into cache so mono_class_get_checked () will find it.
10203 Skip nested types as those should not be available on the global scope. */
10204 if (!tb->nesting_type)
10205 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10208 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10209 by performing a mono_class_get which does the full resolution.
10211 Working around this semantics would require us to write a lot of code for no clear advantage.
10213 mono_image_append_class_to_reflection_info_set (klass);
10215 g_assert (mono_class_get_ref_info (klass) == tb);
10218 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10220 if (parent != NULL) {
10221 mono_class_setup_parent (klass, parent);
10222 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10223 const char *old_n = klass->name;
10224 /* trick to get relative numbering right when compiling corlib */
10225 klass->name = "BuildingObject";
10226 mono_class_setup_parent (klass, mono_defaults.object_class);
10227 klass->name = old_n;
10230 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10231 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10232 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10233 klass->instance_size = sizeof (MonoObject);
10234 klass->size_inited = 1;
10235 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10238 mono_class_setup_mono_type (klass);
10240 mono_class_setup_supertypes (klass);
10243 * FIXME: handle interfaces.
10246 tb->type.type = &klass->byval_arg;
10248 if (tb->nesting_type) {
10249 g_assert (tb->nesting_type->type);
10250 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10253 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10255 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10257 mono_loader_unlock ();
10261 mono_loader_unlock ();
10262 mono_error_raise_exception (&error);
10266 * mono_reflection_setup_generic_class:
10267 * @tb: a TypeBuilder object
10269 * Setup the generic class before adding the first generic parameter.
10272 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10277 * mono_reflection_create_generic_class:
10278 * @tb: a TypeBuilder object
10280 * Creates the generic class after all generic parameters have been added.
10283 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10288 klass = mono_class_from_mono_type (tb->type.type);
10290 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10292 if (klass->generic_container || (count == 0))
10295 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10297 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10299 klass->generic_container->owner.klass = klass;
10300 klass->generic_container->type_argc = count;
10301 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10303 klass->is_generic = 1;
10305 for (i = 0; i < count; i++) {
10306 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10307 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10308 klass->generic_container->type_params [i] = *param;
10309 /*Make sure we are a diferent type instance */
10310 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10311 klass->generic_container->type_params [i].info.pklass = NULL;
10312 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10314 g_assert (klass->generic_container->type_params [i].param.owner);
10317 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10321 * mono_reflection_create_internal_class:
10322 * @tb: a TypeBuilder object
10324 * Actually create the MonoClass that is associated with the TypeBuilder.
10327 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10331 klass = mono_class_from_mono_type (tb->type.type);
10333 mono_loader_lock ();
10334 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10335 MonoReflectionFieldBuilder *fb;
10337 MonoType *enum_basetype;
10339 g_assert (tb->fields != NULL);
10340 g_assert (mono_array_length (tb->fields) >= 1);
10342 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10344 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10345 mono_loader_unlock ();
10349 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10350 klass->element_class = mono_class_from_mono_type (enum_basetype);
10351 if (!klass->element_class)
10352 klass->element_class = mono_class_from_mono_type (enum_basetype);
10355 * get the element_class from the current corlib.
10357 ec = default_class_from_mono_type (enum_basetype);
10358 klass->instance_size = ec->instance_size;
10359 klass->size_inited = 1;
10361 * this is almost safe to do with enums and it's needed to be able
10362 * to create objects of the enum type (for use in SetConstant).
10364 /* FIXME: Does this mean enums can't have method overrides ? */
10365 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10367 mono_loader_unlock ();
10370 static MonoMarshalSpec*
10371 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10372 MonoReflectionMarshal *minfo)
10374 MonoMarshalSpec *res;
10376 res = image_g_new0 (image, MonoMarshalSpec, 1);
10377 res->native = minfo->type;
10379 switch (minfo->type) {
10380 case MONO_NATIVE_LPARRAY:
10381 res->data.array_data.elem_type = minfo->eltype;
10382 if (minfo->has_size) {
10383 res->data.array_data.param_num = minfo->param_num;
10384 res->data.array_data.num_elem = minfo->count;
10385 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10388 res->data.array_data.param_num = -1;
10389 res->data.array_data.num_elem = -1;
10390 res->data.array_data.elem_mult = -1;
10394 case MONO_NATIVE_BYVALTSTR:
10395 case MONO_NATIVE_BYVALARRAY:
10396 res->data.array_data.num_elem = minfo->count;
10399 case MONO_NATIVE_CUSTOM:
10400 if (minfo->marshaltyperef)
10401 res->data.custom_data.custom_name =
10402 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10403 if (minfo->mcookie)
10404 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10413 #endif /* !DISABLE_REFLECTION_EMIT */
10415 MonoReflectionMarshalAsAttribute*
10416 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10417 MonoMarshalSpec *spec)
10419 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10420 MonoReflectionMarshalAsAttribute *minfo;
10423 if (!System_Reflection_Emit_MarshalAsAttribute) {
10424 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10425 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10426 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10429 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10430 minfo->utype = spec->native;
10432 switch (minfo->utype) {
10433 case MONO_NATIVE_LPARRAY:
10434 minfo->array_subtype = spec->data.array_data.elem_type;
10435 minfo->size_const = spec->data.array_data.num_elem;
10436 if (spec->data.array_data.param_num != -1)
10437 minfo->size_param_index = spec->data.array_data.param_num;
10440 case MONO_NATIVE_BYVALTSTR:
10441 case MONO_NATIVE_BYVALARRAY:
10442 minfo->size_const = spec->data.array_data.num_elem;
10445 case MONO_NATIVE_CUSTOM:
10446 if (spec->data.custom_data.custom_name) {
10447 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10449 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10451 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10453 if (spec->data.custom_data.cookie)
10454 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10464 #ifndef DISABLE_REFLECTION_EMIT
10466 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10467 ReflectionMethodBuilder *rmb,
10468 MonoMethodSignature *sig)
10472 MonoMethodWrapper *wrapperm;
10473 MonoMarshalSpec **specs;
10474 MonoReflectionMethodAux *method_aux;
10479 mono_error_init (&error);
10481 * Methods created using a MethodBuilder should have their memory allocated
10482 * inside the image mempool, while dynamic methods should have their memory
10485 dynamic = rmb->refs != NULL;
10486 image = dynamic ? NULL : klass->image;
10489 g_assert (!klass->generic_class);
10491 mono_loader_lock ();
10493 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10494 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10495 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10497 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10499 wrapperm = (MonoMethodWrapper*)m;
10501 m->dynamic = dynamic;
10503 m->flags = rmb->attrs;
10504 m->iflags = rmb->iattrs;
10505 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10507 m->signature = sig;
10508 m->sre_method = TRUE;
10509 m->skip_visibility = rmb->skip_visibility;
10510 if (rmb->table_idx)
10511 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10513 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10514 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10515 m->string_ctor = 1;
10517 m->signature->pinvoke = 1;
10518 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10519 m->signature->pinvoke = 1;
10521 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10523 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10524 g_assert (mono_error_ok (&error));
10525 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10526 g_assert (mono_error_ok (&error));
10528 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10530 if (image_is_dynamic (klass->image))
10531 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10533 mono_loader_unlock ();
10536 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10537 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10538 MonoMethodHeader *header;
10540 gint32 max_stack, i;
10541 gint32 num_locals = 0;
10542 gint32 num_clauses = 0;
10546 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10547 code_size = rmb->ilgen->code_len;
10548 max_stack = rmb->ilgen->max_stack;
10549 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10550 if (rmb->ilgen->ex_handlers)
10551 num_clauses = method_count_clauses (rmb->ilgen);
10554 code = mono_array_addr (rmb->code, guint8, 0);
10555 code_size = mono_array_length (rmb->code);
10556 /* we probably need to run a verifier on the code... */
10566 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10567 header->code_size = code_size;
10568 header->code = image_g_malloc (image, code_size);
10569 memcpy ((char*)header->code, code, code_size);
10570 header->max_stack = max_stack;
10571 header->init_locals = rmb->init_locals;
10572 header->num_locals = num_locals;
10574 for (i = 0; i < num_locals; ++i) {
10575 MonoReflectionLocalBuilder *lb =
10576 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10578 header->locals [i] = image_g_new0 (image, MonoType, 1);
10579 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10582 header->num_clauses = num_clauses;
10584 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10585 rmb->ilgen, num_clauses);
10588 wrapperm->header = header;
10591 if (rmb->generic_params) {
10592 int count = mono_array_length (rmb->generic_params);
10593 MonoGenericContainer *container = rmb->generic_container;
10595 g_assert (container);
10597 container->type_argc = count;
10598 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10599 container->owner.method = m;
10601 m->is_generic = TRUE;
10602 mono_method_set_generic_container (m, container);
10604 for (i = 0; i < count; i++) {
10605 MonoReflectionGenericParam *gp =
10606 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10607 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10608 container->type_params [i] = *param;
10612 * The method signature might have pointers to generic parameters that belong to other methods.
10613 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10614 * generic parameters.
10616 for (i = 0; i < m->signature->param_count; ++i) {
10617 MonoType *t = m->signature->params [i];
10618 if (t->type == MONO_TYPE_MVAR) {
10619 MonoGenericParam *gparam = t->data.generic_param;
10620 if (gparam->num < count) {
10621 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10622 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10628 if (klass->generic_container) {
10629 container->parent = klass->generic_container;
10630 container->context.class_inst = klass->generic_container->context.class_inst;
10632 container->context.method_inst = mono_get_shared_generic_inst (container);
10636 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10640 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10642 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10643 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10644 for (i = 0; i < rmb->nrefs; ++i)
10645 data [i + 1] = rmb->refs [i];
10650 /* Parameter info */
10653 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10654 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10655 for (i = 0; i <= m->signature->param_count; ++i) {
10656 MonoReflectionParamBuilder *pb;
10657 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10658 if ((i > 0) && (pb->attrs)) {
10659 /* Make a copy since it might point to a shared type structure */
10660 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10661 m->signature->params [i - 1]->attrs = pb->attrs;
10664 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10665 MonoDynamicImage *assembly;
10666 guint32 idx, def_type, len;
10670 if (!method_aux->param_defaults) {
10671 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10672 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10674 assembly = (MonoDynamicImage*)klass->image;
10675 idx = encode_constant (assembly, pb->def_value, &def_type);
10676 /* Copy the data from the blob since it might get realloc-ed */
10677 p = assembly->blob.data + idx;
10678 len = mono_metadata_decode_blob_size (p, &p2);
10680 method_aux->param_defaults [i] = image_g_malloc (image, len);
10681 method_aux->param_default_types [i] = def_type;
10682 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10686 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10687 g_assert (mono_error_ok (&error));
10690 if (!method_aux->param_cattr)
10691 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10692 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10698 /* Parameter marshalling */
10701 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10702 MonoReflectionParamBuilder *pb;
10703 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10704 if (pb->marshal_info) {
10706 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10707 specs [pb->position] =
10708 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10712 if (specs != NULL) {
10714 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10715 method_aux->param_marshall = specs;
10718 if (image_is_dynamic (klass->image) && method_aux)
10719 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10721 mono_loader_unlock ();
10727 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10729 ReflectionMethodBuilder rmb;
10730 MonoMethodSignature *sig;
10732 mono_loader_lock ();
10733 sig = ctor_builder_to_signature (klass->image, mb);
10734 mono_loader_unlock ();
10736 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10738 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10739 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10741 /* If we are in a generic class, we might be called multiple times from inflate_method */
10742 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10743 /* ilgen is no longer needed */
10747 return mb->mhandle;
10751 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10753 ReflectionMethodBuilder rmb;
10754 MonoMethodSignature *sig;
10756 mono_loader_lock ();
10757 sig = method_builder_to_signature (klass->image, mb);
10758 mono_loader_unlock ();
10760 reflection_methodbuilder_from_method_builder (&rmb, mb);
10762 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10763 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10765 /* If we are in a generic class, we might be called multiple times from inflate_method */
10766 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10767 /* ilgen is no longer needed */
10770 return mb->mhandle;
10773 static MonoClassField*
10774 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10776 MonoClassField *field;
10780 field = g_new0 (MonoClassField, 1);
10782 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10783 g_assert (mono_error_ok (&error));
10784 if (fb->attrs || fb->modreq || fb->modopt) {
10785 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10786 field->type->attrs = fb->attrs;
10788 g_assert (image_is_dynamic (klass->image));
10789 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10790 g_free (field->type);
10791 field->type = mono_metadata_type_dup (klass->image, custom);
10794 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10796 if (fb->offset != -1)
10797 field->offset = fb->offset;
10798 field->parent = klass;
10799 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10801 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10808 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10811 MonoReflectionTypeBuilder *tb = NULL;
10812 gboolean is_dynamic = FALSE;
10813 MonoClass *geninst;
10815 mono_loader_lock ();
10817 if (is_sre_type_builder (mono_object_class (type))) {
10818 tb = (MonoReflectionTypeBuilder *) type;
10821 } else if (is_sre_generic_instance (mono_object_class (type))) {
10822 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10823 MonoReflectionType *gtd = rgi->generic_type;
10825 if (is_sre_type_builder (mono_object_class (gtd))) {
10826 tb = (MonoReflectionTypeBuilder *)gtd;
10831 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10832 if (tb && tb->generic_container)
10833 mono_reflection_create_generic_class (tb);
10835 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10836 if (!klass->generic_container) {
10837 mono_loader_unlock ();
10841 if (klass->wastypebuilder) {
10842 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10847 mono_loader_unlock ();
10849 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10851 return &geninst->byval_arg;
10855 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10857 MonoGenericClass *gclass;
10858 MonoGenericInst *inst;
10860 g_assert (klass->generic_container);
10862 inst = mono_metadata_get_generic_inst (type_argc, types);
10863 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10865 return mono_generic_class_get_class (gclass);
10868 MonoReflectionMethod*
10869 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10873 MonoMethod *method, *inflated;
10874 MonoMethodInflated *imethod;
10875 MonoGenericContext tmp_context;
10876 MonoGenericInst *ginst;
10877 MonoType **type_argv;
10880 /*FIXME but this no longer should happen*/
10881 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10882 #ifndef DISABLE_REFLECTION_EMIT
10883 MonoReflectionMethodBuilder *mb = NULL;
10884 MonoReflectionTypeBuilder *tb;
10887 mb = (MonoReflectionMethodBuilder *) rmethod;
10888 tb = (MonoReflectionTypeBuilder *) mb->type;
10889 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10891 method = methodbuilder_to_mono_method (klass, mb);
10893 g_assert_not_reached ();
10897 method = rmethod->method;
10900 klass = method->klass;
10902 if (method->is_inflated)
10903 method = ((MonoMethodInflated *) method)->declaring;
10905 count = mono_method_signature (method)->generic_param_count;
10906 if (count != mono_array_length (types))
10909 type_argv = g_new0 (MonoType *, count);
10910 for (i = 0; i < count; i++) {
10911 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10912 type_argv [i] = mono_reflection_type_get_handle (garg);
10914 ginst = mono_metadata_get_generic_inst (count, type_argv);
10915 g_free (type_argv);
10917 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10918 tmp_context.method_inst = ginst;
10920 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10921 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10922 imethod = (MonoMethodInflated *) inflated;
10924 /*FIXME but I think this is no longer necessary*/
10925 if (image_is_dynamic (method->klass->image)) {
10926 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10928 * This table maps metadata structures representing inflated methods/fields
10929 * to the reflection objects representing their generic definitions.
10931 mono_image_lock ((MonoImage*)image);
10932 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10933 mono_image_unlock ((MonoImage*)image);
10936 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10937 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10939 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10942 #ifndef DISABLE_REFLECTION_EMIT
10944 static MonoMethod *
10945 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10947 MonoMethodInflated *imethod;
10948 MonoGenericContext *context;
10952 * With generic code sharing the klass might not be inflated.
10953 * This can happen because classes inflated with their own
10954 * type arguments are "normalized" to the uninflated class.
10956 if (!klass->generic_class)
10959 context = mono_class_get_context (klass);
10961 if (klass->method.count && klass->methods) {
10962 /* Find the already created inflated method */
10963 for (i = 0; i < klass->method.count; ++i) {
10964 g_assert (klass->methods [i]->is_inflated);
10965 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10968 g_assert (i < klass->method.count);
10969 imethod = (MonoMethodInflated*)klass->methods [i];
10972 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10973 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10976 if (method->is_generic && image_is_dynamic (method->klass->image)) {
10977 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10979 mono_image_lock ((MonoImage*)image);
10980 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10981 mono_image_unlock ((MonoImage*)image);
10983 return (MonoMethod *) imethod;
10986 static MonoMethod *
10987 inflate_method (MonoReflectionType *type, MonoObject *obj)
10989 MonoMethod *method;
10992 MonoClass *type_class = mono_object_class (type);
10994 if (is_sre_generic_instance (type_class)) {
10995 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10996 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10997 } else if (is_sre_type_builder (type_class)) {
10998 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10999 } else if (type->type) {
11000 gklass = mono_class_from_mono_type (type->type);
11001 gklass = mono_class_get_generic_type_definition (gklass);
11003 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11006 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11007 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11008 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11010 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11011 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11012 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11013 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11014 method = ((MonoReflectionMethod *) obj)->method;
11016 method = NULL; /* prevent compiler warning */
11017 g_error ("can't handle type %s", obj->vtable->klass->name);
11020 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11023 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11025 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11027 MonoGenericClass *gclass;
11028 MonoDynamicGenericClass *dgclass;
11029 MonoClass *klass, *gklass;
11033 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11034 klass = mono_class_from_mono_type (gtype);
11035 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11036 gclass = gtype->data.generic_class;
11038 if (!gclass->is_dynamic)
11041 dgclass = (MonoDynamicGenericClass *) gclass;
11043 if (dgclass->initialized)
11046 gklass = gclass->container_class;
11047 mono_class_init (gklass);
11049 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11051 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11052 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11053 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11055 for (i = 0; i < dgclass->count_fields; i++) {
11056 MonoObject *obj = mono_array_get (fields, gpointer, i);
11057 MonoClassField *field, *inflated_field = NULL;
11059 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11060 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11061 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11062 field = ((MonoReflectionField *) obj)->field;
11064 field = NULL; /* prevent compiler warning */
11065 g_assert_not_reached ();
11068 dgclass->fields [i] = *field;
11069 dgclass->fields [i].parent = klass;
11070 dgclass->fields [i].type = mono_class_inflate_generic_type (
11071 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11072 dgclass->field_generic_types [i] = field->type;
11073 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11074 dgclass->field_objects [i] = obj;
11076 if (inflated_field) {
11077 g_free (inflated_field);
11079 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11083 dgclass->initialized = TRUE;
11087 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11089 MonoDynamicGenericClass *dgclass;
11092 g_assert (gclass->is_dynamic);
11094 dgclass = (MonoDynamicGenericClass *)gclass;
11096 for (i = 0; i < dgclass->count_fields; ++i) {
11097 MonoClassField *field = dgclass->fields + i;
11098 mono_metadata_free_type (field->type);
11099 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11104 fix_partial_generic_class (MonoClass *klass)
11106 MonoClass *gklass = klass->generic_class->container_class;
11107 MonoDynamicGenericClass *dgclass;
11110 if (klass->wastypebuilder)
11113 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11114 if (klass->parent != gklass->parent) {
11116 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11117 if (mono_error_ok (&error)) {
11118 MonoClass *parent = mono_class_from_mono_type (parent_type);
11119 mono_metadata_free_type (parent_type);
11120 if (parent != klass->parent) {
11121 /*fool mono_class_setup_parent*/
11122 klass->supertypes = NULL;
11123 mono_class_setup_parent (klass, parent);
11126 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11127 mono_error_cleanup (&error);
11128 if (gklass->wastypebuilder)
11129 klass->wastypebuilder = TRUE;
11134 if (!dgclass->initialized)
11137 if (klass->method.count != gklass->method.count) {
11138 klass->method.count = gklass->method.count;
11139 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11141 for (i = 0; i < klass->method.count; i++) {
11143 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11144 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11145 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11149 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11150 klass->interface_count = gklass->interface_count;
11151 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11152 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11154 for (i = 0; i < gklass->interface_count; ++i) {
11155 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11156 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11157 mono_metadata_free_type (iface_type);
11159 ensure_runtime_vtable (klass->interfaces [i]);
11161 klass->interfaces_inited = 1;
11164 if (klass->field.count != gklass->field.count) {
11165 klass->field.count = gklass->field.count;
11166 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11168 for (i = 0; i < klass->field.count; i++) {
11169 klass->fields [i] = gklass->fields [i];
11170 klass->fields [i].parent = klass;
11171 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11175 /*We can only finish with this klass once it's parent has as well*/
11176 if (gklass->wastypebuilder)
11177 klass->wastypebuilder = TRUE;
11182 ensure_generic_class_runtime_vtable (MonoClass *klass)
11184 MonoClass *gklass = klass->generic_class->container_class;
11186 ensure_runtime_vtable (gklass);
11188 fix_partial_generic_class (klass);
11192 ensure_runtime_vtable (MonoClass *klass)
11194 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11197 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11200 ensure_runtime_vtable (klass->parent);
11203 num = tb->ctors? mono_array_length (tb->ctors): 0;
11204 num += tb->num_methods;
11205 klass->method.count = num;
11206 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11207 num = tb->ctors? mono_array_length (tb->ctors): 0;
11208 for (i = 0; i < num; ++i)
11209 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11210 num = tb->num_methods;
11212 for (i = 0; i < num; ++i)
11213 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11215 if (tb->interfaces) {
11216 klass->interface_count = mono_array_length (tb->interfaces);
11217 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11218 for (i = 0; i < klass->interface_count; ++i) {
11219 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11220 klass->interfaces [i] = mono_class_from_mono_type (iface);
11221 ensure_runtime_vtable (klass->interfaces [i]);
11223 klass->interfaces_inited = 1;
11225 } else if (klass->generic_class){
11226 ensure_generic_class_runtime_vtable (klass);
11229 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11231 for (i = 0; i < klass->method.count; ++i) {
11232 MonoMethod *im = klass->methods [i];
11233 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11234 im->slot = slot_num++;
11237 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11238 mono_class_setup_interface_offsets (klass);
11239 mono_class_setup_interface_id (klass);
11243 * The generic vtable is needed even if image->run is not set since some
11244 * runtime code like ves_icall_Type_GetMethodsByName depends on
11245 * method->slot being defined.
11249 * tb->methods could not be freed since it is used for determining
11250 * overrides during dynamic vtable construction.
11255 mono_reflection_method_get_handle (MonoObject *method)
11257 MonoClass *class = mono_object_class (method);
11258 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11259 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11260 return sr_method->method;
11262 if (is_sre_method_builder (class)) {
11263 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11264 return mb->mhandle;
11266 if (is_sre_method_on_tb_inst (class)) {
11267 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11268 MonoMethod *result;
11269 /*FIXME move this to a proper method and unify with resolve_object*/
11270 if (m->method_args) {
11271 result = mono_reflection_method_on_tb_inst_get_handle (m);
11273 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11274 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11275 MonoMethod *mono_method;
11277 if (is_sre_method_builder (mono_object_class (m->mb)))
11278 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11279 else if (is_sr_mono_method (mono_object_class (m->mb)))
11280 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11282 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)));
11284 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11289 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11296 MonoReflectionTypeBuilder *tb;
11298 MonoReflectionMethod *m;
11301 *num_overrides = 0;
11303 g_assert (image_is_dynamic (klass->image));
11305 if (!mono_class_get_ref_info (klass))
11308 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11310 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11314 for (i = 0; i < tb->num_methods; ++i) {
11315 MonoReflectionMethodBuilder *mb =
11316 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11317 if (mb->override_methods)
11318 onum += mono_array_length (mb->override_methods);
11323 *overrides = g_new0 (MonoMethod*, onum * 2);
11326 for (i = 0; i < tb->num_methods; ++i) {
11327 MonoReflectionMethodBuilder *mb =
11328 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11329 if (mb->override_methods) {
11330 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11331 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11333 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11334 (*overrides) [onum * 2 + 1] = mb->mhandle;
11336 g_assert (mb->mhandle);
11344 *num_overrides = onum;
11348 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11350 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11351 MonoReflectionFieldBuilder *fb;
11352 MonoClassField *field;
11353 MonoImage *image = klass->image;
11354 const char *p, *p2;
11356 guint32 len, idx, real_size = 0;
11358 klass->field.count = tb->num_fields;
11359 klass->field.first = 0;
11361 mono_error_init (error);
11363 if (tb->class_size) {
11364 if ((tb->packing_size & 0xffffff00) != 0) {
11365 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11366 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11369 klass->packing_size = tb->packing_size;
11370 real_size = klass->instance_size + tb->class_size;
11373 if (!klass->field.count) {
11374 klass->instance_size = MAX (klass->instance_size, real_size);
11378 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11379 mono_class_alloc_ext (klass);
11380 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11382 This is, guess what, a hack.
11383 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11384 On the static path no field class is resolved, only types are built. This is the right thing to do
11386 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11388 klass->size_inited = 1;
11390 for (i = 0; i < klass->field.count; ++i) {
11391 MonoArray *rva_data;
11392 fb = mono_array_get (tb->fields, gpointer, i);
11393 field = &klass->fields [i];
11394 field->name = mono_string_to_utf8_image (image, fb->name, error);
11395 if (!mono_error_ok (error))
11398 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11399 field->type->attrs = fb->attrs;
11401 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11404 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11405 char *base = mono_array_addr (rva_data, char, 0);
11406 size_t size = mono_array_length (rva_data);
11407 char *data = mono_image_alloc (klass->image, size);
11408 memcpy (data, base, size);
11409 klass->ext->field_def_values [i].data = data;
11411 if (fb->offset != -1)
11412 field->offset = fb->offset;
11413 field->parent = klass;
11414 fb->handle = field;
11415 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11417 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11418 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11420 if (fb->def_value) {
11421 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11422 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11423 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11424 /* Copy the data from the blob since it might get realloc-ed */
11425 p = assembly->blob.data + idx;
11426 len = mono_metadata_decode_blob_size (p, &p2);
11428 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11429 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11433 klass->instance_size = MAX (klass->instance_size, real_size);
11434 mono_class_layout_fields (klass);
11438 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11440 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11441 MonoReflectionPropertyBuilder *pb;
11442 MonoImage *image = klass->image;
11443 MonoProperty *properties;
11446 mono_error_init (error);
11449 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11451 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11452 klass->ext->property.first = 0;
11454 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11455 klass->ext->properties = properties;
11456 for (i = 0; i < klass->ext->property.count; ++i) {
11457 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11458 properties [i].parent = klass;
11459 properties [i].attrs = pb->attrs;
11460 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11461 if (!mono_error_ok (error))
11463 if (pb->get_method)
11464 properties [i].get = pb->get_method->mhandle;
11465 if (pb->set_method)
11466 properties [i].set = pb->set_method->mhandle;
11468 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11469 if (pb->def_value) {
11471 const char *p, *p2;
11472 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11473 if (!klass->ext->prop_def_values)
11474 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11475 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11476 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11477 /* Copy the data from the blob since it might get realloc-ed */
11478 p = assembly->blob.data + idx;
11479 len = mono_metadata_decode_blob_size (p, &p2);
11481 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11482 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11487 MonoReflectionEvent *
11488 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11490 MonoEvent *event = g_new0 (MonoEvent, 1);
11493 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11495 event->parent = klass;
11496 event->attrs = eb->attrs;
11497 event->name = mono_string_to_utf8 (eb->name);
11498 if (eb->add_method)
11499 event->add = eb->add_method->mhandle;
11500 if (eb->remove_method)
11501 event->remove = eb->remove_method->mhandle;
11502 if (eb->raise_method)
11503 event->raise = eb->raise_method->mhandle;
11505 #ifndef MONO_SMALL_CONFIG
11506 if (eb->other_methods) {
11508 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11509 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11510 MonoReflectionMethodBuilder *mb =
11511 mono_array_get (eb->other_methods,
11512 MonoReflectionMethodBuilder*, j);
11513 event->other [j] = mb->mhandle;
11518 return mono_event_get_object (mono_object_domain (tb), klass, event);
11522 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11524 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11525 MonoReflectionEventBuilder *eb;
11526 MonoImage *image = klass->image;
11530 mono_error_init (error);
11533 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11535 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11536 klass->ext->event.first = 0;
11538 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11539 klass->ext->events = events;
11540 for (i = 0; i < klass->ext->event.count; ++i) {
11541 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11542 events [i].parent = klass;
11543 events [i].attrs = eb->attrs;
11544 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11545 if (!mono_error_ok (error))
11547 if (eb->add_method)
11548 events [i].add = eb->add_method->mhandle;
11549 if (eb->remove_method)
11550 events [i].remove = eb->remove_method->mhandle;
11551 if (eb->raise_method)
11552 events [i].raise = eb->raise_method->mhandle;
11554 #ifndef MONO_SMALL_CONFIG
11555 if (eb->other_methods) {
11557 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11558 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11559 MonoReflectionMethodBuilder *mb =
11560 mono_array_get (eb->other_methods,
11561 MonoReflectionMethodBuilder*, j);
11562 events [i].other [j] = mb->mhandle;
11566 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11571 remove_instantiations_of_and_ensure_contents (gpointer key,
11573 gpointer user_data)
11575 MonoType *type = (MonoType*)key;
11576 MonoClass *klass = (MonoClass*)user_data;
11578 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11579 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11586 check_array_for_usertypes (MonoArray *arr)
11593 for (i = 0; i < mono_array_length (arr); ++i)
11594 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11597 MonoReflectionType*
11598 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11602 MonoDomain* domain;
11603 MonoReflectionType* res;
11606 domain = mono_object_domain (tb);
11607 klass = mono_class_from_mono_type (tb->type.type);
11610 * Check for user defined Type subclasses.
11612 RESOLVE_TYPE (tb->parent);
11613 check_array_for_usertypes (tb->interfaces);
11615 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11616 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11618 RESOLVE_TYPE (fb->type);
11619 check_array_for_usertypes (fb->modreq);
11620 check_array_for_usertypes (fb->modopt);
11621 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11622 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11627 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11628 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11630 RESOLVE_TYPE (mb->rtype);
11631 check_array_for_usertypes (mb->return_modreq);
11632 check_array_for_usertypes (mb->return_modopt);
11633 check_array_for_usertypes (mb->parameters);
11634 if (mb->param_modreq)
11635 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11636 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11637 if (mb->param_modopt)
11638 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11639 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11644 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11645 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11647 check_array_for_usertypes (mb->parameters);
11648 if (mb->param_modreq)
11649 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11650 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11651 if (mb->param_modopt)
11652 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11653 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11658 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11661 * we need to lock the domain because the lock will be taken inside
11662 * So, we need to keep the locking order correct.
11664 mono_loader_lock ();
11665 mono_domain_lock (domain);
11666 if (klass->wastypebuilder) {
11667 mono_domain_unlock (domain);
11668 mono_loader_unlock ();
11669 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11672 * Fields to set in klass:
11673 * the various flags: delegate/unicode/contextbound etc.
11675 klass->flags = tb->attrs;
11676 klass->has_cctor = 1;
11677 klass->has_finalize = 1;
11678 klass->has_finalize_inited = 1;
11680 mono_class_setup_parent (klass, klass->parent);
11681 /* fool mono_class_setup_supertypes */
11682 klass->supertypes = NULL;
11683 mono_class_setup_supertypes (klass);
11684 mono_class_setup_mono_type (klass);
11687 if (!((MonoDynamicImage*)klass->image)->run) {
11688 if (klass->generic_container) {
11689 /* FIXME: The code below can't handle generic classes */
11690 klass->wastypebuilder = TRUE;
11691 mono_loader_unlock ();
11692 mono_domain_unlock (domain);
11693 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11698 /* enums are done right away */
11699 if (!klass->enumtype)
11700 ensure_runtime_vtable (klass);
11702 if (tb->subtypes) {
11703 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11704 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11705 mono_class_alloc_ext (klass);
11706 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)));
11710 klass->nested_classes_inited = TRUE;
11712 /* fields and object layout */
11713 if (klass->parent) {
11714 if (!klass->parent->size_inited)
11715 mono_class_init (klass->parent);
11716 klass->instance_size = klass->parent->instance_size;
11717 klass->sizes.class_size = 0;
11718 klass->min_align = klass->parent->min_align;
11719 /* if the type has no fields we won't call the field_setup
11720 * routine which sets up klass->has_references.
11722 klass->has_references |= klass->parent->has_references;
11724 klass->instance_size = sizeof (MonoObject);
11725 klass->min_align = 1;
11728 /* FIXME: handle packing_size and instance_size */
11729 typebuilder_setup_fields (klass, &error);
11730 if (!mono_error_ok (&error))
11732 typebuilder_setup_properties (klass, &error);
11733 if (!mono_error_ok (&error))
11736 typebuilder_setup_events (klass, &error);
11737 if (!mono_error_ok (&error))
11740 klass->wastypebuilder = TRUE;
11743 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11744 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11745 * we want to return normal System.MonoType objects, so clear these out from the cache.
11747 * Together with this we must ensure the contents of all instances to match the created type.
11749 if (domain->type_hash && klass->generic_container)
11750 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11752 mono_domain_unlock (domain);
11753 mono_loader_unlock ();
11755 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11756 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11757 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11760 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11761 g_assert (res != (MonoReflectionType*)tb);
11766 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11767 klass->wastypebuilder = TRUE;
11768 mono_domain_unlock (domain);
11769 mono_loader_unlock ();
11770 mono_error_raise_exception (&error);
11775 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11777 MonoGenericParamFull *param;
11782 image = &gparam->tbuilder->module->dynamic_image->image;
11784 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11786 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11787 g_assert (mono_error_ok (&error));
11788 param->param.num = gparam->index;
11790 if (gparam->mbuilder) {
11791 if (!gparam->mbuilder->generic_container) {
11792 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11793 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11794 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11795 gparam->mbuilder->generic_container->is_method = TRUE;
11797 * Cannot set owner.method, since the MonoMethod is not created yet.
11798 * Set the image field instead, so type_in_image () works.
11800 gparam->mbuilder->generic_container->image = klass->image;
11802 param->param.owner = gparam->mbuilder->generic_container;
11803 } else if (gparam->tbuilder) {
11804 if (!gparam->tbuilder->generic_container) {
11805 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11806 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11807 gparam->tbuilder->generic_container->owner.klass = klass;
11809 param->param.owner = gparam->tbuilder->generic_container;
11812 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11814 gparam->type.type = &pklass->byval_arg;
11816 mono_class_set_ref_info (pklass, gparam);
11817 mono_image_append_class_to_reflection_info_set (pklass);
11821 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11823 MonoReflectionModuleBuilder *module = sig->module;
11824 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11825 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11830 check_array_for_usertypes (sig->arguments);
11832 sigbuffer_init (&buf, 32);
11834 sigbuffer_add_value (&buf, 0x07);
11835 sigbuffer_add_value (&buf, na);
11836 if (assembly != NULL){
11837 for (i = 0; i < na; ++i) {
11838 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11839 encode_reflection_type (assembly, type, &buf);
11843 buflen = buf.p - buf.buf;
11844 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11845 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11846 sigbuffer_free (&buf);
11852 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11854 MonoDynamicImage *assembly = sig->module->dynamic_image;
11855 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11860 check_array_for_usertypes (sig->arguments);
11862 sigbuffer_init (&buf, 32);
11864 sigbuffer_add_value (&buf, 0x06);
11865 for (i = 0; i < na; ++i) {
11866 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11867 encode_reflection_type (assembly, type, &buf);
11870 buflen = buf.p - buf.buf;
11871 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11872 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11873 sigbuffer_free (&buf);
11879 MonoMethod *handle;
11880 MonoDomain *domain;
11881 } DynamicMethodReleaseData;
11884 * The runtime automatically clean up those after finalization.
11886 static MonoReferenceQueue *dynamic_method_queue;
11889 free_dynamic_method (void *dynamic_method)
11891 DynamicMethodReleaseData *data = dynamic_method;
11892 MonoDomain *domain = data->domain;
11893 MonoMethod *method = data->handle;
11896 mono_domain_lock (domain);
11897 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11898 g_hash_table_remove (domain->method_to_dyn_method, method);
11899 mono_domain_unlock (domain);
11900 g_assert (dis_link);
11901 mono_gchandle_free (dis_link);
11903 mono_runtime_free_method (domain, method);
11908 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11910 MonoReferenceQueue *queue;
11911 MonoMethod *handle;
11912 DynamicMethodReleaseData *release_data;
11913 ReflectionMethodBuilder rmb;
11914 MonoMethodSignature *sig;
11916 MonoDomain *domain;
11920 if (mono_runtime_is_shutting_down ())
11921 mono_raise_exception (mono_get_exception_invalid_operation (""));
11923 if (!(queue = dynamic_method_queue)) {
11924 mono_loader_lock ();
11925 if (!(queue = dynamic_method_queue))
11926 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11927 mono_loader_unlock ();
11930 sig = dynamic_method_to_signature (mb);
11932 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11935 * Resolve references.
11938 * Every second entry in the refs array is reserved for storing handle_class,
11939 * which is needed by the ldtoken implementation in the JIT.
11941 rmb.nrefs = mb->nrefs;
11942 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11943 for (i = 0; i < mb->nrefs; i += 2) {
11944 MonoClass *handle_class;
11946 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11948 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11949 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11951 * The referenced DynamicMethod should already be created by the managed
11952 * code, except in the case of circular references. In that case, we store
11953 * method in the refs array, and fix it up later when the referenced
11954 * DynamicMethod is created.
11956 if (method->mhandle) {
11957 ref = method->mhandle;
11959 /* FIXME: GC object stored in unmanaged memory */
11962 /* FIXME: GC object stored in unmanaged memory */
11963 method->referenced_by = g_slist_append (method->referenced_by, mb);
11965 handle_class = mono_defaults.methodhandle_class;
11967 MonoException *ex = NULL;
11968 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11970 ex = mono_get_exception_type_load (NULL, NULL);
11971 else if (mono_security_core_clr_enabled ())
11972 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11976 mono_raise_exception (ex);
11981 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11982 rmb.refs [i + 1] = handle_class;
11985 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11987 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11988 release_data = g_new (DynamicMethodReleaseData, 1);
11989 release_data->handle = handle;
11990 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11991 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11992 g_free (release_data);
11994 /* Fix up refs entries pointing at us */
11995 for (l = mb->referenced_by; l; l = l->next) {
11996 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11997 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12000 g_assert (method->mhandle);
12002 data = (gpointer*)wrapper->method_data;
12003 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12004 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12005 data [i + 1] = mb->mhandle;
12008 g_slist_free (mb->referenced_by);
12012 /* ilgen is no longer needed */
12015 domain = mono_domain_get ();
12016 mono_domain_lock (domain);
12017 if (!domain->method_to_dyn_method)
12018 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12019 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12020 mono_domain_unlock (domain);
12023 #endif /* DISABLE_REFLECTION_EMIT */
12027 * mono_reflection_is_valid_dynamic_token:
12029 * Returns TRUE if token is valid.
12033 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12035 return lookup_dyn_token (image, token) != NULL;
12038 MonoMethodSignature *
12039 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12041 MonoMethodSignature *sig;
12042 g_assert (image_is_dynamic (image));
12044 mono_error_init (error);
12046 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12050 return mono_method_signature_checked (method, error);
12053 #ifndef DISABLE_REFLECTION_EMIT
12056 * mono_reflection_lookup_dynamic_token:
12058 * Finish the Builder object pointed to by TOKEN and return the corresponding
12059 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12060 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12063 * LOCKING: Take the loader lock
12066 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12068 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12072 obj = lookup_dyn_token (assembly, token);
12075 g_error ("Could not find required dynamic token 0x%08x", token);
12081 handle_class = &klass;
12082 return resolve_object (image, obj, handle_class, context);
12086 * ensure_complete_type:
12088 * Ensure that KLASS is completed if it is a dynamic type, or references
12092 ensure_complete_type (MonoClass *klass)
12094 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12095 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12097 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12099 // Asserting here could break a lot of code
12100 //g_assert (klass->wastypebuilder);
12103 if (klass->generic_class) {
12104 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12107 for (i = 0; i < inst->type_argc; ++i) {
12108 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12114 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12116 gpointer result = NULL;
12118 if (strcmp (obj->vtable->klass->name, "String") == 0) {
12119 result = mono_string_intern ((MonoString*)obj);
12120 *handle_class = mono_defaults.string_class;
12122 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12123 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12124 MonoClass *mc = mono_class_from_mono_type (type);
12125 if (!mono_class_init (mc))
12126 mono_raise_exception (mono_class_get_exception_for_failure (mc));
12129 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12130 result = mono_class_from_mono_type (inflated);
12131 mono_metadata_free_type (inflated);
12133 result = mono_class_from_mono_type (type);
12135 *handle_class = mono_defaults.typehandle_class;
12137 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12138 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12139 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12140 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12141 result = ((MonoReflectionMethod*)obj)->method;
12144 result = mono_class_inflate_generic_method_checked (result, context, &error);
12145 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12147 *handle_class = mono_defaults.methodhandle_class;
12149 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12150 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12151 result = mb->mhandle;
12153 /* Type is not yet created */
12154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12156 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12159 * Hopefully this has been filled in by calling CreateType() on the
12163 * TODO: This won't work if the application finishes another
12164 * TypeBuilder instance instead of this one.
12166 result = mb->mhandle;
12170 result = mono_class_inflate_generic_method_checked (result, context, &error);
12171 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12173 *handle_class = mono_defaults.methodhandle_class;
12174 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12175 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12177 result = cb->mhandle;
12179 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12181 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12182 result = cb->mhandle;
12186 result = mono_class_inflate_generic_method_checked (result, context, &error);
12187 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12189 *handle_class = mono_defaults.methodhandle_class;
12190 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12191 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12193 ensure_complete_type (field->parent);
12195 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12196 MonoClass *class = mono_class_from_mono_type (inflated);
12197 MonoClassField *inflated_field;
12198 gpointer iter = NULL;
12199 mono_metadata_free_type (inflated);
12200 while ((inflated_field = mono_class_get_fields (class, &iter))) {
12201 if (!strcmp (field->name, inflated_field->name))
12204 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12205 result = inflated_field;
12209 *handle_class = mono_defaults.fieldhandle_class;
12211 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12212 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12213 result = fb->handle;
12216 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12218 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12219 result = fb->handle;
12222 if (fb->handle && fb->handle->parent->generic_container) {
12223 MonoClass *klass = fb->handle->parent;
12224 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12225 MonoClass *inflated = mono_class_from_mono_type (type);
12227 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12229 mono_metadata_free_type (type);
12231 *handle_class = mono_defaults.fieldhandle_class;
12232 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12233 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12234 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12237 klass = type->data.klass;
12238 if (klass->wastypebuilder) {
12239 /* Already created */
12243 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12244 result = type->data.klass;
12247 *handle_class = mono_defaults.typehandle_class;
12248 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12249 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12250 MonoMethodSignature *sig;
12253 if (helper->arguments)
12254 nargs = mono_array_length (helper->arguments);
12258 sig = mono_metadata_signature_alloc (image, nargs);
12259 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12260 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12262 if (helper->unmanaged_call_conv) { /* unmanaged */
12263 sig->call_convention = helper->unmanaged_call_conv - 1;
12264 sig->pinvoke = TRUE;
12265 } else if (helper->call_conv & 0x02) {
12266 sig->call_convention = MONO_CALL_VARARG;
12268 sig->call_convention = MONO_CALL_DEFAULT;
12271 sig->param_count = nargs;
12272 /* TODO: Copy type ? */
12273 sig->ret = helper->return_type->type;
12274 for (i = 0; i < nargs; ++i)
12275 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12278 *handle_class = NULL;
12279 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12280 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12281 /* Already created by the managed code */
12282 g_assert (method->mhandle);
12283 result = method->mhandle;
12284 *handle_class = mono_defaults.methodhandle_class;
12285 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12286 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12287 type = mono_class_inflate_generic_type (type, context);
12288 result = mono_class_from_mono_type (type);
12289 *handle_class = mono_defaults.typehandle_class;
12291 mono_metadata_free_type (type);
12292 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12293 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12294 type = mono_class_inflate_generic_type (type, context);
12295 result = mono_class_from_mono_type (type);
12296 *handle_class = mono_defaults.typehandle_class;
12298 mono_metadata_free_type (type);
12299 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12300 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12301 MonoClass *inflated;
12303 MonoClassField *field;
12305 if (is_sre_field_builder (mono_object_class (f->fb)))
12306 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12307 else if (is_sr_mono_field (mono_object_class (f->fb)))
12308 field = ((MonoReflectionField*)f->fb)->field;
12310 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)));
12312 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12313 inflated = mono_class_from_mono_type (type);
12315 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12316 ensure_complete_type (field->parent);
12318 mono_metadata_free_type (type);
12319 *handle_class = mono_defaults.fieldhandle_class;
12320 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12321 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12322 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12323 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12324 MonoMethod *method;
12326 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12327 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12328 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12329 method = ((MonoReflectionMethod *)c->cb)->method;
12331 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)));
12333 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12334 *handle_class = mono_defaults.methodhandle_class;
12335 mono_metadata_free_type (type);
12336 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12337 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12338 if (m->method_args) {
12339 result = mono_reflection_method_on_tb_inst_get_handle (m);
12342 result = mono_class_inflate_generic_method_checked (result, context, &error);
12343 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12346 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12347 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12348 MonoMethod *method;
12350 if (is_sre_method_builder (mono_object_class (m->mb)))
12351 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12352 else if (is_sr_mono_method (mono_object_class (m->mb)))
12353 method = ((MonoReflectionMethod *)m->mb)->method;
12355 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)));
12357 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12358 mono_metadata_free_type (type);
12360 *handle_class = mono_defaults.methodhandle_class;
12361 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12362 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12365 MonoMethod *method;
12369 mtype = mono_reflection_type_get_handle (m->parent);
12370 klass = mono_class_from_mono_type (mtype);
12372 /* Find the method */
12374 name = mono_string_to_utf8 (m->name);
12376 while ((method = mono_class_get_methods (klass, &iter))) {
12377 if (!strcmp (method->name, name))
12384 // FIXME: Check parameters/return value etc. match
12387 *handle_class = mono_defaults.methodhandle_class;
12388 } else if (is_sre_array (mono_object_get_class(obj)) ||
12389 is_sre_byref (mono_object_get_class(obj)) ||
12390 is_sre_pointer (mono_object_get_class(obj))) {
12391 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12392 MonoType *type = mono_reflection_type_get_handle (ref_type);
12395 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12396 result = mono_class_from_mono_type (inflated);
12397 mono_metadata_free_type (inflated);
12399 result = mono_class_from_mono_type (type);
12401 *handle_class = mono_defaults.typehandle_class;
12403 g_print ("%s\n", obj->vtable->klass->name);
12404 g_assert_not_reached ();
12409 #else /* DISABLE_REFLECTION_EMIT */
12412 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12414 g_assert_not_reached ();
12419 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12421 g_assert_not_reached ();
12425 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12427 g_assert_not_reached ();
12431 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12433 g_assert_not_reached ();
12437 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12439 g_assert_not_reached ();
12443 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12445 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12449 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12451 g_assert_not_reached ();
12455 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12457 g_assert_not_reached ();
12460 MonoReflectionModule *
12461 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12463 g_assert_not_reached ();
12468 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12470 g_assert_not_reached ();
12475 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12477 g_assert_not_reached ();
12482 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12483 gboolean create_open_instance, gboolean register_token)
12485 g_assert_not_reached ();
12490 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12495 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12497 g_assert_not_reached ();
12501 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12504 *num_overrides = 0;
12507 MonoReflectionEvent *
12508 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12510 g_assert_not_reached ();
12514 MonoReflectionType*
12515 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12517 g_assert_not_reached ();
12522 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12524 g_assert_not_reached ();
12528 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12530 g_assert_not_reached ();
12535 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12537 g_assert_not_reached ();
12542 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12547 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12553 mono_reflection_type_get_handle (MonoReflectionType* ref)
12561 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12563 g_assert_not_reached ();
12566 #endif /* DISABLE_REFLECTION_EMIT */
12568 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12569 const static guint32 declsec_flags_map[] = {
12570 0x00000000, /* empty */
12571 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12572 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12573 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12574 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12575 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12576 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12577 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12578 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12579 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12580 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12581 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12582 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12583 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12584 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12585 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12586 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12587 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12588 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12592 * Returns flags that includes all available security action associated to the handle.
12593 * @token: metadata token (either for a class or a method)
12594 * @image: image where resides the metadata.
12597 mono_declsec_get_flags (MonoImage *image, guint32 token)
12599 int index = mono_metadata_declsec_from_index (image, token);
12600 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12601 guint32 result = 0;
12605 /* HasSecurity can be present for other, not specially encoded, attributes,
12606 e.g. SuppressUnmanagedCodeSecurityAttribute */
12610 for (i = index; i < t->rows; i++) {
12611 guint32 cols [MONO_DECL_SECURITY_SIZE];
12613 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12614 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12617 action = cols [MONO_DECL_SECURITY_ACTION];
12618 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12619 result |= declsec_flags_map [action];
12621 g_assert_not_reached ();
12628 * Get the security actions (in the form of flags) associated with the specified method.
12630 * @method: The method for which we want the declarative security flags.
12631 * Return the declarative security flags for the method (only).
12633 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12634 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12637 mono_declsec_flags_from_method (MonoMethod *method)
12639 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12640 /* FIXME: No cache (for the moment) */
12641 guint32 idx = mono_method_get_index (method);
12642 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12643 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12644 return mono_declsec_get_flags (method->klass->image, idx);
12650 * Get the security actions (in the form of flags) associated with the specified class.
12652 * @klass: The class for which we want the declarative security flags.
12653 * Return the declarative security flags for the class.
12655 * Note: We cache the flags inside the MonoClass structure as this will get
12656 * called very often (at least for each method).
12659 mono_declsec_flags_from_class (MonoClass *klass)
12661 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12662 if (!klass->ext || !klass->ext->declsec_flags) {
12665 idx = mono_metadata_token_index (klass->type_token);
12666 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12667 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12668 mono_loader_lock ();
12669 mono_class_alloc_ext (klass);
12670 mono_loader_unlock ();
12671 /* we cache the flags on classes */
12672 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12674 return klass->ext->declsec_flags;
12680 * Get the security actions (in the form of flags) associated with the specified assembly.
12682 * @assembly: The assembly for which we want the declarative security flags.
12683 * Return the declarative security flags for the assembly.
12686 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12688 guint32 idx = 1; /* there is only one assembly */
12689 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12690 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12691 return mono_declsec_get_flags (assembly->image, idx);
12696 * Fill actions for the specific index (which may either be an encoded class token or
12697 * an encoded method token) from the metadata image.
12698 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12701 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12702 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12704 MonoBoolean result = FALSE;
12706 guint32 cols [MONO_DECL_SECURITY_SIZE];
12707 int index = mono_metadata_declsec_from_index (image, token);
12710 t = &image->tables [MONO_TABLE_DECLSECURITY];
12711 for (i = index; i < t->rows; i++) {
12712 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12714 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12717 /* if present only replace (class) permissions with method permissions */
12718 /* if empty accept either class or method permissions */
12719 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12720 if (!actions->demand.blob) {
12721 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12722 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12723 actions->demand.blob = (char*) (blob + 2);
12724 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12727 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12728 if (!actions->noncasdemand.blob) {
12729 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12730 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12731 actions->noncasdemand.blob = (char*) (blob + 2);
12732 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12735 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12736 if (!actions->demandchoice.blob) {
12737 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12738 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12739 actions->demandchoice.blob = (char*) (blob + 2);
12740 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12750 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12751 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12753 guint32 idx = mono_metadata_token_index (klass->type_token);
12754 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12755 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12756 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12760 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12761 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12763 guint32 idx = mono_method_get_index (method);
12764 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12765 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12766 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12770 * Collect all actions (that requires to generate code in mini) assigned for
12771 * the specified method.
12772 * Note: Don't use the content of actions if the function return FALSE.
12775 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12777 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12778 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12779 MonoBoolean result = FALSE;
12782 /* quick exit if no declarative security is present in the metadata */
12783 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12786 /* we want the original as the wrapper is "free" of the security informations */
12787 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12788 method = mono_marshal_method_from_wrapper (method);
12793 /* First we look for method-level attributes */
12794 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12795 mono_class_init (method->klass);
12796 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12798 result = mono_declsec_get_method_demands_params (method, demands,
12799 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12802 /* Here we use (or create) the class declarative cache to look for demands */
12803 flags = mono_declsec_flags_from_class (method->klass);
12804 if (flags & mask) {
12806 mono_class_init (method->klass);
12807 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12809 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12810 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12813 /* The boolean return value is used as a shortcut in case nothing needs to
12814 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12820 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12822 * Note: Don't use the content of actions if the function return FALSE.
12825 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12827 MonoBoolean result = FALSE;
12830 /* quick exit if no declarative security is present in the metadata */
12831 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12834 /* we want the original as the wrapper is "free" of the security informations */
12835 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12836 method = mono_marshal_method_from_wrapper (method);
12841 /* results are independant - zeroize both */
12842 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12843 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12845 /* First we look for method-level attributes */
12846 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12847 mono_class_init (method->klass);
12849 result = mono_declsec_get_method_demands_params (method, cmethod,
12850 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12853 /* Here we use (or create) the class declarative cache to look for demands */
12854 flags = mono_declsec_flags_from_class (method->klass);
12855 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12856 mono_class_init (method->klass);
12858 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12859 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12866 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12868 * @klass The inherited class - this is the class that provides the security check (attributes)
12870 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12872 * Note: Don't use the content of actions if the function return FALSE.
12875 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12877 MonoBoolean result = FALSE;
12880 /* quick exit if no declarative security is present in the metadata */
12881 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12884 /* Here we use (or create) the class declarative cache to look for demands */
12885 flags = mono_declsec_flags_from_class (klass);
12886 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12887 mono_class_init (klass);
12888 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12890 result |= mono_declsec_get_class_demands_params (klass, demands,
12891 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12898 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12900 * Note: Don't use the content of actions if the function return FALSE.
12903 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12905 /* quick exit if no declarative security is present in the metadata */
12906 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12909 /* we want the original as the wrapper is "free" of the security informations */
12910 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12911 method = mono_marshal_method_from_wrapper (method);
12916 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12917 mono_class_init (method->klass);
12918 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12920 return mono_declsec_get_method_demands_params (method, demands,
12921 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12928 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12930 guint32 cols [MONO_DECL_SECURITY_SIZE];
12934 int index = mono_metadata_declsec_from_index (image, token);
12938 t = &image->tables [MONO_TABLE_DECLSECURITY];
12939 for (i = index; i < t->rows; i++) {
12940 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12942 /* shortcut - index are ordered */
12943 if (token != cols [MONO_DECL_SECURITY_PARENT])
12946 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12947 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12948 entry->blob = (char*) (metadata + 2);
12949 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12958 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12960 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12961 guint32 idx = mono_method_get_index (method);
12962 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12963 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12964 return get_declsec_action (method->klass->image, idx, action, entry);
12970 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12973 guint32 flags = mono_declsec_flags_from_class (klass);
12974 if (declsec_flags_map [action] & flags) {
12975 guint32 idx = mono_metadata_token_index (klass->type_token);
12976 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12977 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12978 return get_declsec_action (klass->image, idx, action, entry);
12984 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12986 guint32 idx = 1; /* there is only one assembly */
12987 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12988 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12990 return get_declsec_action (assembly->image, idx, action, entry);
12994 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12996 MonoObject *res, *exc;
12998 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12999 static MonoMethod *method = NULL;
13001 if (!System_Reflection_Emit_TypeBuilder) {
13002 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13003 g_assert (System_Reflection_Emit_TypeBuilder);
13005 if (method == NULL) {
13006 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13011 * The result of mono_type_get_object () might be a System.MonoType but we
13012 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13014 g_assert (mono_class_get_ref_info (klass));
13015 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13017 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13019 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13023 return *(MonoBoolean*)mono_object_unbox (res);
13027 * mono_reflection_type_get_type:
13028 * @reftype: the System.Type object
13030 * Returns the MonoType* associated with the C# System.Type object @reftype.
13033 mono_reflection_type_get_type (MonoReflectionType *reftype)
13035 g_assert (reftype);
13037 return mono_reflection_type_get_handle (reftype);
13041 * mono_reflection_assembly_get_assembly:
13042 * @refassembly: the System.Reflection.Assembly object
13044 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13047 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13049 g_assert (refassembly);
13051 return refassembly->assembly;