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>
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA 0x00002000
63 MonoReflectionILGen *ilgen;
64 MonoReflectionType *rtype;
65 MonoArray *parameters;
66 MonoArray *generic_params;
67 MonoGenericContainer *generic_container;
73 guint32 *table_idx; /* note: it's a pointer */
77 MonoBoolean init_locals;
78 MonoBoolean skip_visibility;
79 MonoArray *return_modreq;
80 MonoArray *return_modopt;
81 MonoArray *param_modreq;
82 MonoArray *param_modopt;
83 MonoArray *permissions;
88 int charset, extra_flags, native_cc;
89 MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
94 MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
107 MONO_INTERFACEIMPL_SIZE,
108 MONO_MEMBERREF_SIZE, /* 0x0A */
110 MONO_CUSTOM_ATTR_SIZE,
111 MONO_FIELD_MARSHAL_SIZE,
112 MONO_DECL_SECURITY_SIZE,
113 MONO_CLASS_LAYOUT_SIZE,
114 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115 MONO_STAND_ALONE_SIGNATURE_SIZE,
119 MONO_PROPERTY_MAP_SIZE,
122 MONO_METHOD_SEMA_SIZE,
123 MONO_METHODIMPL_SIZE,
124 MONO_MODULEREF_SIZE, /* 0x1A */
130 MONO_ASSEMBLY_SIZE, /* 0x20 */
131 MONO_ASSEMBLY_PROCESSOR_SIZE,
132 MONO_ASSEMBLYOS_SIZE,
133 MONO_ASSEMBLYREF_SIZE,
134 MONO_ASSEMBLYREFPROC_SIZE,
135 MONO_ASSEMBLYREFOS_SIZE,
139 MONO_NESTED_CLASS_SIZE,
141 MONO_GENERICPARAM_SIZE, /* 0x2A */
142 MONO_METHODSPEC_SIZE,
143 MONO_GENPARCONSTRAINT_SIZE
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
198 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
199 __type = mono_reflection_type_resolve_user_types (__type); \
200 mono_array_set (arr, MonoReflectionType*, index, __type); \
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
219 mono_reflection_init (void)
224 dynamic_image_lock (MonoDynamicImage *image)
226 mono_image_lock ((MonoImage*)image);
230 dynamic_image_unlock (MonoDynamicImage *image)
232 mono_image_unlock ((MonoImage*)image);
236 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
238 dynamic_image_lock (assembly);
239 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
240 dynamic_image_unlock (assembly);
244 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
248 dynamic_image_lock (assembly);
249 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
250 dynamic_image_unlock (assembly);
256 sigbuffer_init (SigBuffer *buf, int size)
258 buf->buf = g_malloc (size);
260 buf->end = buf->buf + size;
264 sigbuffer_make_room (SigBuffer *buf, int size)
266 if (buf->end - buf->p < size) {
267 int new_size = buf->end - buf->buf + size + 32;
268 char *p = g_realloc (buf->buf, new_size);
269 size = buf->p - buf->buf;
272 buf->end = buf->buf + new_size;
277 sigbuffer_add_value (SigBuffer *buf, guint32 val)
279 sigbuffer_make_room (buf, 6);
280 mono_metadata_encode_value (val, buf->p, &buf->p);
284 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
286 sigbuffer_make_room (buf, 1);
292 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
294 sigbuffer_make_room (buf, size);
295 memcpy (buf->p, p, size);
300 sigbuffer_free (SigBuffer *buf)
305 #ifndef DISABLE_REFLECTION_EMIT
309 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
313 image_g_malloc (MonoImage *image, guint size)
316 return mono_image_alloc (image, size);
318 return g_malloc (size);
320 #endif /* !DISABLE_REFLECTION_EMIT */
325 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
329 image_g_malloc0 (MonoImage *image, guint size)
332 return mono_image_alloc0 (image, size);
334 return g_malloc0 (size);
337 #ifndef DISABLE_REFLECTION_EMIT
339 image_strdup (MonoImage *image, const char *s)
342 return mono_image_strdup (image, s);
348 #define image_g_new(image,struct_type, n_structs) \
349 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
351 #define image_g_new0(image,struct_type, n_structs) \
352 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
356 alloc_table (MonoDynamicTable *table, guint nrows)
359 g_assert (table->columns);
360 if (nrows + 1 >= table->alloc_rows) {
361 while (nrows + 1 >= table->alloc_rows) {
362 if (table->alloc_rows == 0)
363 table->alloc_rows = 16;
365 table->alloc_rows *= 2;
368 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
373 make_room_in_stream (MonoDynamicStream *stream, int size)
375 if (size <= stream->alloc_size)
378 while (stream->alloc_size <= size) {
379 if (stream->alloc_size < 4096)
380 stream->alloc_size = 4096;
382 stream->alloc_size *= 2;
385 stream->data = g_realloc (stream->data, stream->alloc_size);
389 string_heap_insert (MonoDynamicStream *sh, const char *str)
393 gpointer oldkey, oldval;
395 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
396 return GPOINTER_TO_UINT (oldval);
398 len = strlen (str) + 1;
401 make_room_in_stream (sh, idx + len);
404 * We strdup the string even if we already copy them in sh->data
405 * so that the string pointers in the hash remain valid even if
406 * we need to realloc sh->data. We may want to avoid that later.
408 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
409 memcpy (sh->data + idx, str, len);
415 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
417 char *name = mono_string_to_utf8 (str);
419 idx = string_heap_insert (sh, name);
424 #ifndef DISABLE_REFLECTION_EMIT
426 string_heap_init (MonoDynamicStream *sh)
429 sh->alloc_size = 4096;
430 sh->data = g_malloc (4096);
431 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
432 string_heap_insert (sh, "");
437 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
441 make_room_in_stream (stream, stream->index + len);
442 memcpy (stream->data + stream->index, data, len);
444 stream->index += len;
446 * align index? Not without adding an additional param that controls it since
447 * we may store a blob value in pieces.
453 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
457 make_room_in_stream (stream, stream->index + len);
458 memset (stream->data + stream->index, 0, len);
460 stream->index += len;
465 stream_data_align (MonoDynamicStream *stream)
468 guint32 count = stream->index % 4;
470 /* we assume the stream data will be aligned */
472 mono_image_add_stream_data (stream, buf, 4 - count);
475 #ifndef DISABLE_REFLECTION_EMIT
477 mono_blob_entry_hash (const char* str)
481 len = mono_metadata_decode_blob_size (str, &str);
485 for (str += 1; str < end; str++)
486 h = (h << 5) - h + *str;
494 mono_blob_entry_equal (const char *str1, const char *str2) {
498 len = mono_metadata_decode_blob_size (str1, &end1);
499 len2 = mono_metadata_decode_blob_size (str2, &end2);
502 return memcmp (end1, end2, len) == 0;
506 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
510 gpointer oldkey, oldval;
512 copy = g_malloc (s1+s2);
513 memcpy (copy, b1, s1);
514 memcpy (copy + s1, b2, s2);
515 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
517 idx = GPOINTER_TO_UINT (oldval);
519 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
520 mono_image_add_stream_data (&assembly->blob, b2, s2);
521 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
527 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
531 guint32 size = buf->p - buf->buf;
533 g_assert (size <= (buf->end - buf->buf));
534 mono_metadata_encode_value (size, b, &b);
535 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
539 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
540 * dest may be misaligned.
543 swap_with_size (char *dest, const char* val, int len, int nelem) {
544 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
547 for (elem = 0; elem < nelem; ++elem) {
573 g_assert_not_reached ();
579 memcpy (dest, val, len * nelem);
584 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
588 guint32 idx = 0, len;
590 len = str->length * 2;
591 mono_metadata_encode_value (len, b, &b);
592 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
594 char *swapped = g_malloc (2 * mono_string_length (str));
595 const char *p = (const char*)mono_string_chars (str);
597 swap_with_size (swapped, p, 2, mono_string_length (str));
598 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
602 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
607 #ifndef DISABLE_REFLECTION_EMIT
609 default_class_from_mono_type (MonoType *type)
611 switch (type->type) {
612 case MONO_TYPE_OBJECT:
613 return mono_defaults.object_class;
615 return mono_defaults.void_class;
616 case MONO_TYPE_BOOLEAN:
617 return mono_defaults.boolean_class;
619 return mono_defaults.char_class;
621 return mono_defaults.sbyte_class;
623 return mono_defaults.byte_class;
625 return mono_defaults.int16_class;
627 return mono_defaults.uint16_class;
629 return mono_defaults.int32_class;
631 return mono_defaults.uint32_class;
633 return mono_defaults.int_class;
635 return mono_defaults.uint_class;
637 return mono_defaults.int64_class;
639 return mono_defaults.uint64_class;
641 return mono_defaults.single_class;
643 return mono_defaults.double_class;
644 case MONO_TYPE_STRING:
645 return mono_defaults.string_class;
647 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
648 g_assert_not_reached ();
656 * mono_class_get_ref_info:
658 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
661 mono_class_get_ref_info (MonoClass *klass)
663 if (klass->ref_info_handle == 0)
666 return mono_gchandle_get_target (klass->ref_info_handle);
670 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
672 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
673 g_assert (klass->ref_info_handle != 0);
677 mono_class_free_ref_info (MonoClass *klass)
679 if (klass->ref_info_handle) {
680 mono_gchandle_free (klass->ref_info_handle);
681 klass->ref_info_handle = 0;
686 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
689 MonoGenericInst *class_inst;
694 class_inst = gclass->context.class_inst;
696 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
697 klass = gclass->container_class;
698 sigbuffer_add_value (buf, klass->byval_arg.type);
699 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
701 sigbuffer_add_value (buf, class_inst->type_argc);
702 for (i = 0; i < class_inst->type_argc; ++i)
703 encode_type (assembly, class_inst->type_argv [i], buf);
708 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
711 g_assert_not_reached ();
716 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
720 case MONO_TYPE_BOOLEAN:
734 case MONO_TYPE_STRING:
735 case MONO_TYPE_OBJECT:
736 case MONO_TYPE_TYPEDBYREF:
737 sigbuffer_add_value (buf, type->type);
740 sigbuffer_add_value (buf, type->type);
741 encode_type (assembly, type->data.type, buf);
743 case MONO_TYPE_SZARRAY:
744 sigbuffer_add_value (buf, type->type);
745 encode_type (assembly, &type->data.klass->byval_arg, buf);
747 case MONO_TYPE_VALUETYPE:
748 case MONO_TYPE_CLASS: {
749 MonoClass *k = mono_class_from_mono_type (type);
751 if (k->generic_container) {
752 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
753 encode_generic_class (assembly, gclass, buf);
756 * Make sure we use the correct type.
758 sigbuffer_add_value (buf, k->byval_arg.type);
760 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
761 * otherwise two typerefs could point to the same type, leading to
762 * verification errors.
764 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
768 case MONO_TYPE_ARRAY:
769 sigbuffer_add_value (buf, type->type);
770 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
771 sigbuffer_add_value (buf, type->data.array->rank);
772 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
773 sigbuffer_add_value (buf, 0);
775 case MONO_TYPE_GENERICINST:
776 encode_generic_class (assembly, type->data.generic_class, buf);
780 sigbuffer_add_value (buf, type->type);
781 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
784 g_error ("need to encode type %x", type->type);
789 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
792 sigbuffer_add_value (buf, MONO_TYPE_VOID);
796 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
800 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
805 for (i = 0; i < mono_array_length (modreq); ++i) {
806 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
807 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
808 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
812 for (i = 0; i < mono_array_length (modopt); ++i) {
813 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
814 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
815 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
820 #ifndef DISABLE_REFLECTION_EMIT
822 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
826 guint32 nparams = sig->param_count;
832 sigbuffer_init (&buf, 32);
834 * FIXME: vararg, explicit_this, differenc call_conv values...
836 idx = sig->call_convention;
838 idx |= 0x20; /* hasthis */
839 if (sig->generic_param_count)
840 idx |= 0x10; /* generic */
841 sigbuffer_add_byte (&buf, idx);
842 if (sig->generic_param_count)
843 sigbuffer_add_value (&buf, sig->generic_param_count);
844 sigbuffer_add_value (&buf, nparams);
845 encode_type (assembly, sig->ret, &buf);
846 for (i = 0; i < nparams; ++i) {
847 if (i == sig->sentinelpos)
848 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
849 encode_type (assembly, sig->params [i], &buf);
851 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
852 sigbuffer_free (&buf);
858 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
861 * FIXME: reuse code from method_encode_signature().
865 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
866 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
867 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
870 sigbuffer_init (&buf, 32);
871 /* LAMESPEC: all the call conv spec is foobared */
872 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
873 if (mb->call_conv & 2)
874 idx |= 0x5; /* vararg */
875 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
876 idx |= 0x20; /* hasthis */
878 idx |= 0x10; /* generic */
879 sigbuffer_add_byte (&buf, idx);
881 sigbuffer_add_value (&buf, ngparams);
882 sigbuffer_add_value (&buf, nparams + notypes);
883 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
884 encode_reflection_type (assembly, mb->rtype, &buf);
885 for (i = 0; i < nparams; ++i) {
886 MonoArray *modreq = NULL;
887 MonoArray *modopt = NULL;
888 MonoReflectionType *pt;
890 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
891 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
892 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
893 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
894 encode_custom_modifiers (assembly, modreq, modopt, &buf);
895 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
896 encode_reflection_type (assembly, pt, &buf);
899 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
900 for (i = 0; i < notypes; ++i) {
901 MonoReflectionType *pt;
903 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
904 encode_reflection_type (assembly, pt, &buf);
907 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
908 sigbuffer_free (&buf);
913 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
915 MonoDynamicTable *table;
917 guint32 idx, sig_idx;
918 guint nl = mono_array_length (ilgen->locals);
922 sigbuffer_init (&buf, 32);
923 sigbuffer_add_value (&buf, 0x07);
924 sigbuffer_add_value (&buf, nl);
925 for (i = 0; i < nl; ++i) {
926 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
929 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
931 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
933 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
934 sigbuffer_free (&buf);
936 if (assembly->standalonesig_cache == NULL)
937 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
938 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
942 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
943 idx = table->next_idx ++;
945 alloc_table (table, table->rows);
946 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
948 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
950 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
956 method_count_clauses (MonoReflectionILGen *ilgen)
958 guint32 num_clauses = 0;
961 MonoILExceptionInfo *ex_info;
962 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
963 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
964 if (ex_info->handlers)
965 num_clauses += mono_array_length (ex_info->handlers);
973 #ifndef DISABLE_REFLECTION_EMIT
974 static MonoExceptionClause*
975 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
977 MonoExceptionClause *clauses;
978 MonoExceptionClause *clause;
979 MonoILExceptionInfo *ex_info;
980 MonoILExceptionBlock *ex_block;
981 guint32 finally_start;
982 int i, j, clause_index;;
984 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
987 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
988 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
989 finally_start = ex_info->start + ex_info->len;
990 if (!ex_info->handlers)
992 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
993 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
994 clause = &(clauses [clause_index]);
996 clause->flags = ex_block->type;
997 clause->try_offset = ex_info->start;
999 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1000 clause->try_len = finally_start - ex_info->start;
1002 clause->try_len = ex_info->len;
1003 clause->handler_offset = ex_block->start;
1004 clause->handler_len = ex_block->len;
1005 if (ex_block->extype) {
1006 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1008 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1009 clause->data.filter_offset = ex_block->filter_offset;
1011 clause->data.filter_offset = 0;
1013 finally_start = ex_block->start + ex_block->len;
1021 #endif /* !DISABLE_REFLECTION_EMIT */
1024 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1029 gint32 max_stack, i;
1030 gint32 num_locals = 0;
1031 gint32 num_exception = 0;
1034 char fat_header [12];
1036 guint16 short_value;
1037 guint32 local_sig = 0;
1038 guint32 header_size = 12;
1041 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1042 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1046 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1048 code = mb->ilgen->code;
1049 code_size = mb->ilgen->code_len;
1050 max_stack = mb->ilgen->max_stack;
1051 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1052 if (mb->ilgen->ex_handlers)
1053 num_exception = method_count_clauses (mb->ilgen);
1057 char *name = mono_string_to_utf8 (mb->name);
1058 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1059 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1062 mono_raise_exception (exception);
1065 code_size = mono_array_length (code);
1066 max_stack = 8; /* we probably need to run a verifier on the code... */
1069 stream_data_align (&assembly->code);
1071 /* check for exceptions, maxstack, locals */
1072 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1074 if (code_size < 64 && !(code_size & 1)) {
1075 flags = (code_size << 2) | 0x2;
1076 } else if (code_size < 32 && (code_size & 1)) {
1077 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1081 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1082 /* add to the fixup todo list */
1083 if (mb->ilgen && mb->ilgen->num_token_fixups)
1084 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1085 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1086 return assembly->text_rva + idx;
1090 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1092 * FIXME: need to set also the header size in fat_flags.
1093 * (and more sects and init locals flags)
1097 fat_flags |= METHOD_HEADER_MORE_SECTS;
1098 if (mb->init_locals)
1099 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1100 fat_header [0] = fat_flags;
1101 fat_header [1] = (header_size / 4 ) << 4;
1102 short_value = GUINT16_TO_LE (max_stack);
1103 memcpy (fat_header + 2, &short_value, 2);
1104 int_value = GUINT32_TO_LE (code_size);
1105 memcpy (fat_header + 4, &int_value, 4);
1106 int_value = GUINT32_TO_LE (local_sig);
1107 memcpy (fat_header + 8, &int_value, 4);
1108 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1109 /* add to the fixup todo list */
1110 if (mb->ilgen && mb->ilgen->num_token_fixups)
1111 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1113 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1114 if (num_exception) {
1115 unsigned char sheader [4];
1116 MonoILExceptionInfo * ex_info;
1117 MonoILExceptionBlock * ex_block;
1120 stream_data_align (&assembly->code);
1121 /* always use fat format for now */
1122 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1123 num_exception *= 6 * sizeof (guint32);
1124 num_exception += 4; /* include the size of the header */
1125 sheader [1] = num_exception & 0xff;
1126 sheader [2] = (num_exception >> 8) & 0xff;
1127 sheader [3] = (num_exception >> 16) & 0xff;
1128 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1129 /* fat header, so we are already aligned */
1131 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1132 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1133 if (ex_info->handlers) {
1134 int finally_start = ex_info->start + ex_info->len;
1135 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1137 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139 val = GUINT32_TO_LE (ex_block->type);
1140 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1142 val = GUINT32_TO_LE (ex_info->start);
1143 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1144 /* need fault, too, probably */
1145 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1146 val = GUINT32_TO_LE (finally_start - ex_info->start);
1148 val = GUINT32_TO_LE (ex_info->len);
1149 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1150 /* handler offset */
1151 val = GUINT32_TO_LE (ex_block->start);
1152 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1154 val = GUINT32_TO_LE (ex_block->len);
1155 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1156 finally_start = ex_block->start + ex_block->len;
1157 if (ex_block->extype) {
1158 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1160 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1161 val = ex_block->filter_offset;
1165 val = GUINT32_TO_LE (val);
1166 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1167 /*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",
1168 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);*/
1171 g_error ("No clauses for ex info block %d", i);
1175 return assembly->text_rva + idx;
1179 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1182 MonoDynamicTable *table;
1185 table = &assembly->tables [table_idx];
1187 g_assert (col < table->columns);
1189 values = table->values + table->columns;
1190 for (i = 1; i <= table->rows; ++i) {
1191 if (values [col] == token)
1193 values += table->columns;
1199 * LOCKING: Acquires the loader lock.
1201 static MonoCustomAttrInfo*
1202 lookup_custom_attr (MonoImage *image, gpointer member)
1204 MonoCustomAttrInfo* res;
1206 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1211 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1217 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1219 /* FIXME: Need to do more checks */
1220 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1221 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1223 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1230 static MonoCustomAttrInfo*
1231 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1233 int i, index, count, not_visible;
1234 MonoCustomAttrInfo *ainfo;
1235 MonoReflectionCustomAttr *cattr;
1239 /* FIXME: check in assembly the Run flag is set */
1241 count = mono_array_length (cattrs);
1243 /* Skip nonpublic attributes since MS.NET seems to do the same */
1244 /* FIXME: This needs to be done more globally */
1246 for (i = 0; i < count; ++i) {
1247 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1248 if (!custom_attr_visible (image, cattr))
1251 count -= not_visible;
1253 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1255 ainfo->image = image;
1256 ainfo->num_attrs = count;
1257 ainfo->cached = alloc_img != NULL;
1259 for (i = 0; i < count; ++i) {
1260 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1261 if (custom_attr_visible (image, cattr)) {
1262 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1263 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1264 ainfo->attrs [index].ctor = cattr->ctor->method;
1265 ainfo->attrs [index].data = saved;
1266 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1274 #ifndef DISABLE_REFLECTION_EMIT
1276 * LOCKING: Acquires the loader lock.
1279 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1281 MonoCustomAttrInfo *ainfo, *tmp;
1283 if (!cattrs || !mono_array_length (cattrs))
1286 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1288 mono_loader_lock ();
1289 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1291 mono_custom_attrs_free (tmp);
1292 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1293 mono_loader_unlock ();
1299 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1306 * idx is the table index of the object
1307 * type is one of MONO_CUSTOM_ATTR_*
1310 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1312 MonoDynamicTable *table;
1313 MonoReflectionCustomAttr *cattr;
1315 guint32 count, i, token;
1317 char *p = blob_size;
1319 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1322 count = mono_array_length (cattrs);
1323 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1324 table->rows += count;
1325 alloc_table (table, table->rows);
1326 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1327 idx <<= MONO_CUSTOM_ATTR_BITS;
1329 for (i = 0; i < count; ++i) {
1330 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1331 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1332 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1333 type = mono_metadata_token_index (token);
1334 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1335 switch (mono_metadata_token_table (token)) {
1336 case MONO_TABLE_METHOD:
1337 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1339 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1340 * method, not the one returned by mono_image_create_token ().
1342 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1344 case MONO_TABLE_MEMBERREF:
1345 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1348 g_warning ("got wrong token in custom attr");
1351 values [MONO_CUSTOM_ATTR_TYPE] = type;
1353 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1354 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1355 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1356 values += MONO_CUSTOM_ATTR_SIZE;
1362 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1364 MonoDynamicTable *table;
1366 guint32 count, i, idx;
1367 MonoReflectionPermissionSet *perm;
1372 count = mono_array_length (permissions);
1373 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1374 table->rows += count;
1375 alloc_table (table, table->rows);
1377 for (i = 0; i < mono_array_length (permissions); ++i) {
1378 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1380 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1382 idx = mono_metadata_token_index (parent_token);
1383 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1384 switch (mono_metadata_token_table (parent_token)) {
1385 case MONO_TABLE_TYPEDEF:
1386 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1388 case MONO_TABLE_METHOD:
1389 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1391 case MONO_TABLE_ASSEMBLY:
1392 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1395 g_assert_not_reached ();
1398 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1399 values [MONO_DECL_SECURITY_PARENT] = idx;
1400 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1407 * Fill in the MethodDef and ParamDef tables for a method.
1408 * This is used for both normal methods and constructors.
1411 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1413 MonoDynamicTable *table;
1417 /* room in this table is already allocated */
1418 table = &assembly->tables [MONO_TABLE_METHOD];
1419 *mb->table_idx = table->next_idx ++;
1420 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1421 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1422 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1423 values [MONO_METHOD_FLAGS] = mb->attrs;
1424 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1425 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1426 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1428 table = &assembly->tables [MONO_TABLE_PARAM];
1429 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1431 mono_image_add_decl_security (assembly,
1432 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1435 MonoDynamicTable *mtable;
1438 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1439 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1442 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1443 if (mono_array_get (mb->pinfo, gpointer, i))
1446 table->rows += count;
1447 alloc_table (table, table->rows);
1448 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1449 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1450 MonoReflectionParamBuilder *pb;
1451 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1452 values [MONO_PARAM_FLAGS] = pb->attrs;
1453 values [MONO_PARAM_SEQUENCE] = i;
1454 if (pb->name != NULL) {
1455 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1457 values [MONO_PARAM_NAME] = 0;
1459 values += MONO_PARAM_SIZE;
1460 if (pb->marshal_info) {
1462 alloc_table (mtable, mtable->rows);
1463 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1464 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1465 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1467 pb->table_idx = table->next_idx++;
1468 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1469 guint32 field_type = 0;
1470 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1472 alloc_table (mtable, mtable->rows);
1473 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1474 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1475 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1476 mvalues [MONO_CONSTANT_TYPE] = field_type;
1477 mvalues [MONO_CONSTANT_PADDING] = 0;
1484 #ifndef DISABLE_REFLECTION_EMIT
1486 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1488 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1490 rmb->ilgen = mb->ilgen;
1491 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1492 rmb->parameters = mb->parameters;
1493 rmb->generic_params = mb->generic_params;
1494 rmb->generic_container = mb->generic_container;
1495 rmb->opt_types = NULL;
1496 rmb->pinfo = mb->pinfo;
1497 rmb->attrs = mb->attrs;
1498 rmb->iattrs = mb->iattrs;
1499 rmb->call_conv = mb->call_conv;
1500 rmb->code = mb->code;
1501 rmb->type = mb->type;
1502 rmb->name = mb->name;
1503 rmb->table_idx = &mb->table_idx;
1504 rmb->init_locals = mb->init_locals;
1505 rmb->skip_visibility = FALSE;
1506 rmb->return_modreq = mb->return_modreq;
1507 rmb->return_modopt = mb->return_modopt;
1508 rmb->param_modreq = mb->param_modreq;
1509 rmb->param_modopt = mb->param_modopt;
1510 rmb->permissions = mb->permissions;
1511 rmb->mhandle = mb->mhandle;
1516 rmb->charset = mb->charset;
1517 rmb->extra_flags = mb->extra_flags;
1518 rmb->native_cc = mb->native_cc;
1519 rmb->dllentry = mb->dllentry;
1525 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1527 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1529 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1531 rmb->ilgen = mb->ilgen;
1532 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1533 rmb->parameters = mb->parameters;
1534 rmb->generic_params = NULL;
1535 rmb->generic_container = NULL;
1536 rmb->opt_types = NULL;
1537 rmb->pinfo = mb->pinfo;
1538 rmb->attrs = mb->attrs;
1539 rmb->iattrs = mb->iattrs;
1540 rmb->call_conv = mb->call_conv;
1542 rmb->type = mb->type;
1543 rmb->name = mono_string_new (mono_domain_get (), name);
1544 rmb->table_idx = &mb->table_idx;
1545 rmb->init_locals = mb->init_locals;
1546 rmb->skip_visibility = FALSE;
1547 rmb->return_modreq = NULL;
1548 rmb->return_modopt = NULL;
1549 rmb->param_modreq = mb->param_modreq;
1550 rmb->param_modopt = mb->param_modopt;
1551 rmb->permissions = mb->permissions;
1552 rmb->mhandle = mb->mhandle;
1558 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1560 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1562 rmb->ilgen = mb->ilgen;
1563 rmb->rtype = mb->rtype;
1564 rmb->parameters = mb->parameters;
1565 rmb->generic_params = NULL;
1566 rmb->generic_container = NULL;
1567 rmb->opt_types = NULL;
1569 rmb->attrs = mb->attrs;
1571 rmb->call_conv = mb->call_conv;
1573 rmb->type = (MonoObject *) mb->owner;
1574 rmb->name = mb->name;
1575 rmb->table_idx = NULL;
1576 rmb->init_locals = mb->init_locals;
1577 rmb->skip_visibility = mb->skip_visibility;
1578 rmb->return_modreq = NULL;
1579 rmb->return_modopt = NULL;
1580 rmb->param_modreq = NULL;
1581 rmb->param_modopt = NULL;
1582 rmb->permissions = NULL;
1583 rmb->mhandle = mb->mhandle;
1590 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1592 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1593 MonoDynamicTable *table;
1596 MonoReflectionMethod *m;
1599 if (!mb->override_methods)
1602 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1603 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1605 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1607 alloc_table (table, table->rows);
1608 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1609 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1610 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1612 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1613 switch (mono_metadata_token_table (tok)) {
1614 case MONO_TABLE_MEMBERREF:
1615 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1617 case MONO_TABLE_METHOD:
1618 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1621 g_assert_not_reached ();
1623 values [MONO_METHODIMPL_DECLARATION] = tok;
1627 #ifndef DISABLE_REFLECTION_EMIT
1629 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1631 MonoDynamicTable *table;
1633 ReflectionMethodBuilder rmb;
1636 reflection_methodbuilder_from_method_builder (&rmb, mb);
1638 mono_image_basic_method (&rmb, assembly);
1639 mb->table_idx = *rmb.table_idx;
1641 if (mb->dll) { /* It's a P/Invoke method */
1643 /* map CharSet values to on-disk values */
1644 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1645 int extra_flags = mb->extra_flags;
1646 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1648 alloc_table (table, table->rows);
1649 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1651 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1652 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1654 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1656 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1657 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1658 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1659 table = &assembly->tables [MONO_TABLE_MODULEREF];
1661 alloc_table (table, table->rows);
1662 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1663 values [MONO_IMPLMAP_SCOPE] = table->rows;
1667 if (mb->generic_params) {
1668 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1669 table->rows += mono_array_length (mb->generic_params);
1670 alloc_table (table, table->rows);
1671 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1672 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1674 mono_image_get_generic_param_info (
1675 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1682 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1684 ReflectionMethodBuilder rmb;
1686 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1688 mono_image_basic_method (&rmb, assembly);
1689 mb->table_idx = *rmb.table_idx;
1694 type_get_fully_qualified_name (MonoType *type)
1696 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1700 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1704 klass = mono_class_from_mono_type (type);
1706 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1707 ta = klass->image->assembly;
1708 if (assembly_is_dynamic (ta) || (ta == ass)) {
1709 if (klass->generic_class || klass->generic_container)
1710 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1711 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1713 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1716 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1719 #ifndef DISABLE_REFLECTION_EMIT
1720 /*field_image is the image to which the eventual custom mods have been encoded against*/
1722 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1725 guint32 idx, i, token;
1727 if (!assembly->save)
1730 sigbuffer_init (&buf, 32);
1732 sigbuffer_add_value (&buf, 0x06);
1733 /* encode custom attributes before the type */
1734 if (type->num_mods) {
1735 for (i = 0; i < type->num_mods; ++i) {
1738 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1739 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1741 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1743 token = type->modifiers [i].token;
1746 if (type->modifiers [i].required)
1747 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1749 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1751 sigbuffer_add_value (&buf, token);
1754 encode_type (assembly, type, &buf);
1755 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1756 sigbuffer_free (&buf);
1762 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1766 guint32 typespec = 0;
1770 init_type_builder_generics (fb->type);
1772 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1773 class = mono_class_from_mono_type (type);
1775 sigbuffer_init (&buf, 32);
1777 sigbuffer_add_value (&buf, 0x06);
1778 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1779 /* encode custom attributes before the type */
1781 if (class->generic_container)
1782 typespec = create_typespec (assembly, type);
1785 MonoGenericClass *gclass;
1786 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1787 encode_generic_class (assembly, gclass, &buf);
1789 encode_type (assembly, type, &buf);
1791 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1792 sigbuffer_free (&buf);
1797 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1798 char blob_size [64];
1799 char *b = blob_size;
1802 guint32 idx = 0, len = 0, dummy = 0;
1804 buf = g_malloc (64);
1806 *ret_type = MONO_TYPE_CLASS;
1808 box_val = (char*)&dummy;
1810 box_val = ((char*)val) + sizeof (MonoObject);
1811 *ret_type = val->vtable->klass->byval_arg.type;
1814 switch (*ret_type) {
1815 case MONO_TYPE_BOOLEAN:
1820 case MONO_TYPE_CHAR:
1837 case MONO_TYPE_VALUETYPE: {
1838 MonoClass *klass = val->vtable->klass;
1840 if (klass->enumtype) {
1841 *ret_type = mono_class_enum_basetype (klass)->type;
1843 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1846 g_error ("we can't encode valuetypes, we should have never reached this line");
1849 case MONO_TYPE_CLASS:
1851 case MONO_TYPE_STRING: {
1852 MonoString *str = (MonoString*)val;
1853 /* there is no signature */
1854 len = str->length * 2;
1855 mono_metadata_encode_value (len, b, &b);
1856 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1858 char *swapped = g_malloc (2 * mono_string_length (str));
1859 const char *p = (const char*)mono_string_chars (str);
1861 swap_with_size (swapped, p, 2, mono_string_length (str));
1862 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1866 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1872 case MONO_TYPE_GENERICINST:
1873 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1876 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1879 /* there is no signature */
1880 mono_metadata_encode_value (len, b, &b);
1881 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1882 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1883 swap_with_size (blob_size, box_val, len, 1);
1884 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1886 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1894 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1899 sigbuffer_init (&buf, 32);
1901 sigbuffer_add_value (&buf, minfo->type);
1903 switch (minfo->type) {
1904 case MONO_NATIVE_BYVALTSTR:
1905 case MONO_NATIVE_BYVALARRAY:
1906 sigbuffer_add_value (&buf, minfo->count);
1908 case MONO_NATIVE_LPARRAY:
1909 if (minfo->eltype || minfo->has_size) {
1910 sigbuffer_add_value (&buf, minfo->eltype);
1911 if (minfo->has_size) {
1912 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1913 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1915 /* LAMESPEC: ElemMult is undocumented */
1916 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1920 case MONO_NATIVE_SAFEARRAY:
1922 sigbuffer_add_value (&buf, minfo->eltype);
1924 case MONO_NATIVE_CUSTOM:
1926 str = mono_string_to_utf8 (minfo->guid);
1928 sigbuffer_add_value (&buf, len);
1929 sigbuffer_add_mem (&buf, str, len);
1932 sigbuffer_add_value (&buf, 0);
1934 /* native type name */
1935 sigbuffer_add_value (&buf, 0);
1936 /* custom marshaler type name */
1937 if (minfo->marshaltype || minfo->marshaltyperef) {
1938 if (minfo->marshaltyperef)
1939 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1941 str = mono_string_to_utf8 (minfo->marshaltype);
1943 sigbuffer_add_value (&buf, len);
1944 sigbuffer_add_mem (&buf, str, len);
1947 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1948 sigbuffer_add_value (&buf, 0);
1950 if (minfo->mcookie) {
1951 str = mono_string_to_utf8 (minfo->mcookie);
1953 sigbuffer_add_value (&buf, len);
1954 sigbuffer_add_mem (&buf, str, len);
1957 sigbuffer_add_value (&buf, 0);
1963 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1964 sigbuffer_free (&buf);
1969 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1971 MonoDynamicTable *table;
1974 /* maybe this fixup should be done in the C# code */
1975 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1976 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1977 table = &assembly->tables [MONO_TABLE_FIELD];
1978 fb->table_idx = table->next_idx ++;
1979 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1980 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1981 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1982 values [MONO_FIELD_FLAGS] = fb->attrs;
1983 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1985 if (fb->offset != -1) {
1986 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1988 alloc_table (table, table->rows);
1989 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1990 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1991 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1993 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1994 guint32 field_type = 0;
1995 table = &assembly->tables [MONO_TABLE_CONSTANT];
1997 alloc_table (table, table->rows);
1998 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1999 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2000 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2001 values [MONO_CONSTANT_TYPE] = field_type;
2002 values [MONO_CONSTANT_PADDING] = 0;
2004 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2006 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2008 alloc_table (table, table->rows);
2009 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2010 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2012 * We store it in the code section because it's simpler for now.
2015 if (mono_array_length (fb->rva_data) >= 10)
2016 stream_data_align (&assembly->code);
2017 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2019 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2020 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2022 if (fb->marshal_info) {
2023 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2025 alloc_table (table, table->rows);
2026 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2027 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2028 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2033 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2036 guint32 nparams = 0;
2037 MonoReflectionMethodBuilder *mb = fb->get_method;
2038 MonoReflectionMethodBuilder *smb = fb->set_method;
2041 if (mb && mb->parameters)
2042 nparams = mono_array_length (mb->parameters);
2043 if (!mb && smb && smb->parameters)
2044 nparams = mono_array_length (smb->parameters) - 1;
2045 sigbuffer_init (&buf, 32);
2046 if (fb->call_conv & 0x20)
2047 sigbuffer_add_byte (&buf, 0x28);
2049 sigbuffer_add_byte (&buf, 0x08);
2050 sigbuffer_add_value (&buf, nparams);
2052 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2053 for (i = 0; i < nparams; ++i) {
2054 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2055 encode_reflection_type (assembly, pt, &buf);
2057 } else if (smb && smb->parameters) {
2058 /* the property type is the last param */
2059 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2060 for (i = 0; i < nparams; ++i) {
2061 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2062 encode_reflection_type (assembly, pt, &buf);
2065 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2068 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2069 sigbuffer_free (&buf);
2074 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2076 MonoDynamicTable *table;
2078 guint num_methods = 0;
2082 * we need to set things in the following tables:
2083 * PROPERTYMAP (info already filled in _get_type_info ())
2084 * PROPERTY (rows already preallocated in _get_type_info ())
2085 * METHOD (method info already done with the generic method code)
2089 table = &assembly->tables [MONO_TABLE_PROPERTY];
2090 pb->table_idx = table->next_idx ++;
2091 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2092 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2093 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2094 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2096 /* FIXME: we still don't handle 'other' methods */
2097 if (pb->get_method) num_methods ++;
2098 if (pb->set_method) num_methods ++;
2100 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2101 table->rows += num_methods;
2102 alloc_table (table, table->rows);
2104 if (pb->get_method) {
2105 semaidx = table->next_idx ++;
2106 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2107 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2108 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2109 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2111 if (pb->set_method) {
2112 semaidx = table->next_idx ++;
2113 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2114 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2115 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2116 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2118 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2119 guint32 field_type = 0;
2120 table = &assembly->tables [MONO_TABLE_CONSTANT];
2122 alloc_table (table, table->rows);
2123 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2124 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2125 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2126 values [MONO_CONSTANT_TYPE] = field_type;
2127 values [MONO_CONSTANT_PADDING] = 0;
2132 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2134 MonoDynamicTable *table;
2136 guint num_methods = 0;
2140 * we need to set things in the following tables:
2141 * EVENTMAP (info already filled in _get_type_info ())
2142 * EVENT (rows already preallocated in _get_type_info ())
2143 * METHOD (method info already done with the generic method code)
2146 table = &assembly->tables [MONO_TABLE_EVENT];
2147 eb->table_idx = table->next_idx ++;
2148 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2149 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2150 values [MONO_EVENT_FLAGS] = eb->attrs;
2151 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2154 * FIXME: we still don't handle 'other' methods
2156 if (eb->add_method) num_methods ++;
2157 if (eb->remove_method) num_methods ++;
2158 if (eb->raise_method) num_methods ++;
2160 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2161 table->rows += num_methods;
2162 alloc_table (table, table->rows);
2164 if (eb->add_method) {
2165 semaidx = table->next_idx ++;
2166 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2167 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2168 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2169 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2171 if (eb->remove_method) {
2172 semaidx = table->next_idx ++;
2173 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2174 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2175 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2176 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2178 if (eb->raise_method) {
2179 semaidx = table->next_idx ++;
2180 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2181 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2182 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2183 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2188 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2190 MonoDynamicTable *table;
2191 guint32 num_constraints, i;
2195 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2196 num_constraints = gparam->iface_constraints ?
2197 mono_array_length (gparam->iface_constraints) : 0;
2198 table->rows += num_constraints;
2199 if (gparam->base_type)
2201 alloc_table (table, table->rows);
2203 if (gparam->base_type) {
2204 table_idx = table->next_idx ++;
2205 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2207 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2208 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2209 assembly, mono_reflection_type_get_handle (gparam->base_type));
2212 for (i = 0; i < num_constraints; i++) {
2213 MonoReflectionType *constraint = mono_array_get (
2214 gparam->iface_constraints, gpointer, i);
2216 table_idx = table->next_idx ++;
2217 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2219 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2220 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2221 assembly, mono_reflection_type_get_handle (constraint));
2226 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2228 GenericParamTableEntry *entry;
2231 * The GenericParam table must be sorted according to the `owner' field.
2232 * We need to do this sorting prior to writing the GenericParamConstraint
2233 * table, since we have to use the final GenericParam table indices there
2234 * and they must also be sorted.
2237 entry = g_new0 (GenericParamTableEntry, 1);
2238 entry->owner = owner;
2239 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2240 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2241 entry->gparam = gparam;
2243 g_ptr_array_add (assembly->gen_params, entry);
2247 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2249 MonoDynamicTable *table;
2250 MonoGenericParam *param;
2254 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2255 table_idx = table->next_idx ++;
2256 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2258 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2260 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2261 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2262 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2263 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2265 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2267 encode_constraints (entry->gparam, table_idx, assembly);
2271 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2273 MonoDynamicTable *table;
2276 guint32 cols [MONO_ASSEMBLY_SIZE];
2280 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2283 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2284 table = &assembly->tables [MONO_TABLE_MODULEREF];
2285 token = table->next_idx ++;
2287 alloc_table (table, table->rows);
2288 values = table->values + token * MONO_MODULEREF_SIZE;
2289 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2291 token <<= MONO_RESOLUTION_SCOPE_BITS;
2292 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2293 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2298 if (assembly_is_dynamic (image->assembly))
2300 memset (cols, 0, sizeof (cols));
2302 /* image->assembly->image is the manifest module */
2303 image = image->assembly->image;
2304 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2307 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2308 token = table->next_idx ++;
2310 alloc_table (table, table->rows);
2311 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2312 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2313 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2314 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2315 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2316 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2317 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2318 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2319 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2321 if (strcmp ("", image->assembly->aname.culture)) {
2322 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2323 image->assembly->aname.culture);
2326 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2327 guchar pubtoken [9];
2329 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2330 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2332 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2334 token <<= MONO_RESOLUTION_SCOPE_BITS;
2335 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2336 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2341 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2343 MonoDynamicTable *table;
2348 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2351 sigbuffer_init (&buf, 32);
2352 switch (type->type) {
2353 case MONO_TYPE_FNPTR:
2355 case MONO_TYPE_SZARRAY:
2356 case MONO_TYPE_ARRAY:
2358 case MONO_TYPE_MVAR:
2359 case MONO_TYPE_GENERICINST:
2360 encode_type (assembly, type, &buf);
2362 case MONO_TYPE_CLASS:
2363 case MONO_TYPE_VALUETYPE: {
2364 MonoClass *k = mono_class_from_mono_type (type);
2365 if (!k || !k->generic_container) {
2366 sigbuffer_free (&buf);
2369 encode_type (assembly, type, &buf);
2373 sigbuffer_free (&buf);
2377 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2378 if (assembly->save) {
2379 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2380 alloc_table (table, table->rows + 1);
2381 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2382 values [MONO_TYPESPEC_SIGNATURE] = token;
2384 sigbuffer_free (&buf);
2386 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2387 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2393 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2395 MonoDynamicTable *table;
2397 guint32 token, scope, enclosing;
2400 /* if the type requires a typespec, we must try that first*/
2401 if (try_typespec && (token = create_typespec (assembly, type)))
2403 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2406 klass = mono_class_from_mono_type (type);
2408 klass = mono_class_from_mono_type (type);
2411 * If it's in the same module and not a generic type parameter:
2413 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2414 (type->type != MONO_TYPE_MVAR)) {
2415 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2416 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2417 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2421 if (klass->nested_in) {
2422 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2423 /* get the typeref idx of the enclosing type */
2424 enclosing >>= MONO_TYPEDEFORREF_BITS;
2425 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2427 scope = resolution_scope_from_image (assembly, klass->image);
2429 table = &assembly->tables [MONO_TABLE_TYPEREF];
2430 if (assembly->save) {
2431 alloc_table (table, table->rows + 1);
2432 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2433 values [MONO_TYPEREF_SCOPE] = scope;
2434 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2435 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2437 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2438 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2440 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2445 * Despite the name, we handle also TypeSpec (with the above helper).
2448 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2450 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2453 #ifndef DISABLE_REFLECTION_EMIT
2455 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2457 MonoDynamicTable *table;
2459 guint32 token, pclass;
2461 switch (parent & MONO_TYPEDEFORREF_MASK) {
2462 case MONO_TYPEDEFORREF_TYPEREF:
2463 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2465 case MONO_TYPEDEFORREF_TYPESPEC:
2466 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2468 case MONO_TYPEDEFORREF_TYPEDEF:
2469 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2472 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2475 /* extract the index */
2476 parent >>= MONO_TYPEDEFORREF_BITS;
2478 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2480 if (assembly->save) {
2481 alloc_table (table, table->rows + 1);
2482 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2483 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2484 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2485 values [MONO_MEMBERREF_SIGNATURE] = sig;
2488 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2495 * Insert a memberef row into the metadata: the token that point to the memberref
2496 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2497 * mono_image_get_fieldref_token()).
2498 * The sig param is an index to an already built signature.
2501 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2503 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2504 return mono_image_add_memberef_row (assembly, parent, name, sig);
2509 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2512 MonoMethodSignature *sig;
2514 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2516 if (create_typespec) {
2517 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2522 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2523 if (token && !create_typespec)
2526 g_assert (!method->is_inflated);
2529 * A methodref signature can't contain an unmanaged calling convention.
2531 sig = mono_metadata_signature_dup (mono_method_signature (method));
2532 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2533 sig->call_convention = MONO_CALL_DEFAULT;
2534 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2535 method->name, method_encode_signature (assembly, sig));
2537 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2540 if (create_typespec) {
2541 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2542 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2543 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2545 if (assembly->save) {
2548 alloc_table (table, table->rows + 1);
2549 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2550 values [MONO_METHODSPEC_METHOD] = token;
2551 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2554 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2556 /*methodspec and memberef tokens are diferent, */
2557 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2564 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2566 guint32 token, parent, sig;
2567 ReflectionMethodBuilder rmb;
2569 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2571 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2575 name = mono_string_to_utf8 (method->name);
2576 reflection_methodbuilder_from_method_builder (&rmb, method);
2579 * A methodref signature can't contain an unmanaged calling convention.
2580 * Since some flags are encoded as part of call_conv, we need to check against it.
2582 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2583 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2585 sig = method_builder_encode_signature (assembly, &rmb);
2587 if (tb->generic_params)
2588 parent = create_generic_typespec (assembly, tb);
2590 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2592 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2595 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2600 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2601 const gchar *name, guint32 sig)
2603 MonoDynamicTable *table;
2607 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2609 if (assembly->save) {
2610 alloc_table (table, table->rows + 1);
2611 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2612 values [MONO_MEMBERREF_CLASS] = original;
2613 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2614 values [MONO_MEMBERREF_SIGNATURE] = sig;
2617 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2624 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2628 guint32 nparams = mono_array_length (mb->generic_params);
2631 if (!assembly->save)
2634 sigbuffer_init (&buf, 32);
2636 sigbuffer_add_value (&buf, 0xa);
2637 sigbuffer_add_value (&buf, nparams);
2639 for (i = 0; i < nparams; i++) {
2640 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2641 sigbuffer_add_value (&buf, i);
2644 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2645 sigbuffer_free (&buf);
2650 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2652 MonoDynamicTable *table;
2654 guint32 token, mtoken = 0;
2656 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2660 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2662 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2663 switch (mono_metadata_token_table (mtoken)) {
2664 case MONO_TABLE_MEMBERREF:
2665 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2667 case MONO_TABLE_METHOD:
2668 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2671 g_assert_not_reached ();
2674 if (assembly->save) {
2675 alloc_table (table, table->rows + 1);
2676 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2677 values [MONO_METHODSPEC_METHOD] = mtoken;
2678 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2681 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2684 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2689 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2693 if (mb->generic_params && create_methodspec)
2694 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2696 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2700 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2701 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2706 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2708 guint32 token, parent, sig;
2709 ReflectionMethodBuilder rmb;
2711 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2713 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2717 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2719 if (tb->generic_params)
2720 parent = create_generic_typespec (assembly, tb);
2722 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2724 name = mono_string_to_utf8 (rmb.name);
2725 sig = method_builder_encode_signature (assembly, &rmb);
2727 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2730 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2736 is_field_on_inst (MonoClassField *field)
2738 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2742 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2745 get_field_on_inst_generic_type (MonoClassField *field)
2747 MonoClass *class, *gtd;
2748 MonoDynamicGenericClass *dgclass;
2751 g_assert (is_field_on_inst (field));
2753 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2755 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2756 field_index = field - dgclass->fields;
2757 return dgclass->field_generic_types [field_index];
2760 class = field->parent;
2761 gtd = class->generic_class->container_class;
2763 if (field >= class->fields && field - class->fields < class->field.count) {
2764 field_index = field - class->fields;
2765 return gtd->fields [field_index].type;
2768 g_assert_not_reached ();
2772 #ifndef DISABLE_REFLECTION_EMIT
2774 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2780 g_assert (field->parent);
2782 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2786 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2787 int index = field - field->parent->fields;
2788 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2790 if (is_field_on_inst (field))
2791 type = get_field_on_inst_generic_type (field);
2793 type = mono_field_get_type (field);
2795 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2796 mono_field_get_name (field),
2797 fieldref_encode_signature (assembly, field->parent->image, type));
2798 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2803 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2807 MonoGenericClass *gclass;
2811 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2814 if (is_sre_field_builder (mono_object_class (f->fb))) {
2815 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2816 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2817 klass = mono_class_from_mono_type (type);
2818 gclass = type->data.generic_class;
2819 g_assert (gclass->is_dynamic);
2821 name = mono_string_to_utf8 (fb->name);
2822 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2823 field_encode_signature (assembly, fb));
2825 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2827 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2829 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2830 klass = mono_class_from_mono_type (type);
2832 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2833 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2835 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2836 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2839 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2844 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2848 MonoGenericClass *gclass;
2851 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2853 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2857 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2858 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2859 ReflectionMethodBuilder rmb;
2862 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2863 klass = mono_class_from_mono_type (type);
2865 gclass = type->data.generic_class;
2866 g_assert (gclass->is_dynamic);
2868 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2870 name = mono_string_to_utf8 (rmb.name);
2872 sig = method_builder_encode_signature (assembly, &rmb);
2874 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2876 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2877 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2879 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2880 klass = mono_class_from_mono_type (type);
2882 sig = method_encode_signature (assembly, mono_method_signature (mm));
2883 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2885 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2886 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2890 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2895 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2899 MonoGenericContext tmp_context;
2900 MonoType **type_argv;
2901 MonoGenericInst *ginst;
2902 MonoMethod *method, *inflated;
2905 init_type_builder_generics ((MonoObject*)m->inst);
2907 method = inflate_method (m->inst, (MonoObject*)m->mb);
2909 klass = method->klass;
2911 if (m->method_args == NULL)
2914 if (method->is_inflated)
2915 method = ((MonoMethodInflated *) method)->declaring;
2917 count = mono_array_length (m->method_args);
2919 type_argv = g_new0 (MonoType *, count);
2920 for (i = 0; i < count; i++) {
2921 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2922 type_argv [i] = mono_reflection_type_get_handle (garg);
2924 ginst = mono_metadata_get_generic_inst (count, type_argv);
2927 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2928 tmp_context.method_inst = ginst;
2930 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
2931 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2936 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2938 guint32 sig, token = 0;
2942 if (m->method_args) {
2943 MonoMethod *inflated;
2945 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2946 if (create_methodspec)
2947 token = mono_image_get_methodspec_token (assembly, inflated);
2949 token = mono_image_get_inflated_method_token (assembly, inflated);
2953 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2957 if (is_sre_method_builder (mono_object_class (m->mb))) {
2958 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2959 MonoGenericClass *gclass;
2960 ReflectionMethodBuilder rmb;
2963 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2964 klass = mono_class_from_mono_type (type);
2965 gclass = type->data.generic_class;
2966 g_assert (gclass->is_dynamic);
2968 reflection_methodbuilder_from_method_builder (&rmb, mb);
2970 name = mono_string_to_utf8 (rmb.name);
2972 sig = method_builder_encode_signature (assembly, &rmb);
2974 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2976 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2977 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2979 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2980 klass = mono_class_from_mono_type (type);
2982 sig = method_encode_signature (assembly, mono_method_signature (mm));
2983 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2985 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2986 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2989 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2994 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2998 guint32 nparams = context->method_inst->type_argc;
3001 if (!assembly->save)
3004 sigbuffer_init (&buf, 32);
3006 * FIXME: vararg, explicit_this, differenc call_conv values...
3008 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3009 sigbuffer_add_value (&buf, nparams);
3011 for (i = 0; i < nparams; i++)
3012 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3014 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3015 sigbuffer_free (&buf);
3020 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3022 MonoDynamicTable *table;
3024 guint32 token, mtoken = 0, sig;
3025 MonoMethodInflated *imethod;
3026 MonoMethod *declaring;
3028 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3030 g_assert (method->is_inflated);
3031 imethod = (MonoMethodInflated *) method;
3032 declaring = imethod->declaring;
3034 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3035 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3037 if (!mono_method_signature (declaring)->generic_param_count)
3040 switch (mono_metadata_token_table (mtoken)) {
3041 case MONO_TABLE_MEMBERREF:
3042 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3044 case MONO_TABLE_METHOD:
3045 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3048 g_assert_not_reached ();
3051 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3053 if (assembly->save) {
3054 alloc_table (table, table->rows + 1);
3055 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3056 values [MONO_METHODSPEC_METHOD] = mtoken;
3057 values [MONO_METHODSPEC_SIGNATURE] = sig;
3060 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3067 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3069 MonoMethodInflated *imethod;
3072 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3076 g_assert (method->is_inflated);
3077 imethod = (MonoMethodInflated *) method;
3079 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3080 token = method_encode_methodspec (assembly, method);
3082 guint32 sig = method_encode_signature (
3083 assembly, mono_method_signature (imethod->declaring));
3084 token = mono_image_get_memberref_token (
3085 assembly, &method->klass->byval_arg, method->name, sig);
3088 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3093 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3095 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3098 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3099 token = mono_image_get_memberref_token (
3100 assembly, &m->klass->byval_arg, m->name, sig);
3106 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3108 MonoDynamicTable *table;
3117 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3118 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3119 * Because of this, we must not insert it into the `typeref' hash table.
3121 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3122 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3126 sigbuffer_init (&buf, 32);
3128 g_assert (tb->generic_params);
3129 klass = mono_class_from_mono_type (type);
3131 if (tb->generic_container)
3132 mono_reflection_create_generic_class (tb);
3134 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3135 g_assert (klass->generic_container);
3136 sigbuffer_add_value (&buf, klass->byval_arg.type);
3137 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3139 count = mono_array_length (tb->generic_params);
3140 sigbuffer_add_value (&buf, count);
3141 for (i = 0; i < count; i++) {
3142 MonoReflectionGenericParam *gparam;
3144 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3146 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3149 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3151 if (assembly->save) {
3152 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3153 alloc_table (table, table->rows + 1);
3154 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3155 values [MONO_TYPESPEC_SIGNATURE] = token;
3157 sigbuffer_free (&buf);
3159 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3160 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3166 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3169 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3171 int i, count, len, pos;
3176 count += mono_array_length (modreq);
3178 count += mono_array_length (modopt);
3181 return mono_metadata_type_dup (NULL, type);
3183 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3185 memcpy (t, type, MONO_SIZEOF_TYPE);
3187 t->num_mods = count;
3190 for (i = 0; i < mono_array_length (modreq); ++i) {
3191 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3192 t->modifiers [pos].required = 1;
3193 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3198 for (i = 0; i < mono_array_length (modopt); ++i) {
3199 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3200 t->modifiers [pos].required = 0;
3201 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3210 init_type_builder_generics (MonoObject *type)
3212 MonoReflectionTypeBuilder *tb;
3214 if (!is_sre_type_builder(mono_object_class (type)))
3216 tb = (MonoReflectionTypeBuilder *)type;
3218 if (tb && tb->generic_container)
3219 mono_reflection_create_generic_class (tb);
3223 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3225 MonoDynamicTable *table;
3226 MonoType *custom = NULL, *type;
3228 guint32 token, pclass, parent, sig;
3231 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3235 /* FIXME: is this call necessary? */
3236 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3237 name = mono_string_to_utf8 (fb->name);
3239 /*FIXME this is one more layer of ugliness due how types are created.*/
3240 init_type_builder_generics (fb->type);
3242 /* fb->type does not include the custom modifiers */
3243 /* FIXME: We should do this in one place when a fieldbuilder is created */
3244 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3245 if (fb->modreq || fb->modopt)
3246 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3248 sig = fieldref_encode_signature (assembly, NULL, type);
3251 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3252 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3254 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3255 parent >>= MONO_TYPEDEFORREF_BITS;
3257 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3259 if (assembly->save) {
3260 alloc_table (table, table->rows + 1);
3261 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3262 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3263 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3264 values [MONO_MEMBERREF_SIGNATURE] = sig;
3267 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3269 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3275 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3281 if (!assembly->save)
3284 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3285 g_assert (helper->type == 2);
3287 if (helper->arguments)
3288 nargs = mono_array_length (helper->arguments);
3292 sigbuffer_init (&buf, 32);
3294 /* Encode calling convention */
3295 /* Change Any to Standard */
3296 if ((helper->call_conv & 0x03) == 0x03)
3297 helper->call_conv = 0x01;
3298 /* explicit_this implies has_this */
3299 if (helper->call_conv & 0x40)
3300 helper->call_conv &= 0x20;
3302 if (helper->call_conv == 0) { /* Unmanaged */
3303 idx = helper->unmanaged_call_conv - 1;
3306 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3307 if (helper->call_conv & 0x02) /* varargs */
3311 sigbuffer_add_byte (&buf, idx);
3312 sigbuffer_add_value (&buf, nargs);
3313 encode_reflection_type (assembly, helper->return_type, &buf);
3314 for (i = 0; i < nargs; ++i) {
3315 MonoArray *modreqs = NULL;
3316 MonoArray *modopts = NULL;
3317 MonoReflectionType *pt;
3319 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3320 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3321 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3322 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3324 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3325 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3326 encode_reflection_type (assembly, pt, &buf);
3328 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3329 sigbuffer_free (&buf);
3335 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3338 MonoDynamicTable *table;
3341 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3342 idx = table->next_idx ++;
3344 alloc_table (table, table->rows);
3345 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3347 values [MONO_STAND_ALONE_SIGNATURE] =
3348 mono_reflection_encode_sighelper (assembly, helper);
3354 reflection_cc_to_file (int call_conv) {
3355 switch (call_conv & 0x3) {
3357 case 1: return MONO_CALL_DEFAULT;
3358 case 2: return MONO_CALL_VARARG;
3360 g_assert_not_reached ();
3364 #endif /* !DISABLE_REFLECTION_EMIT */
3368 MonoMethodSignature *sig;
3373 #ifndef DISABLE_REFLECTION_EMIT
3375 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3380 MonoMethodSignature *sig;
3384 name = mono_string_to_utf8 (m->name);
3385 nparams = mono_array_length (m->parameters);
3386 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3388 sig->sentinelpos = -1;
3389 sig->call_convention = reflection_cc_to_file (m->call_conv);
3390 sig->param_count = nparams;
3391 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3392 mtype = mono_reflection_type_get_handle (m->parent);
3393 for (i = 0; i < nparams; ++i)
3394 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3396 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3398 if (strcmp (name, am->name) == 0 &&
3399 mono_metadata_type_equal (am->parent, mtype) &&
3400 mono_metadata_signature_equal (am->sig, sig)) {
3403 m->table_idx = am->token & 0xffffff;
3407 am = g_new0 (ArrayMethod, 1);
3411 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3412 method_encode_signature (assembly, sig));
3413 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3414 m->table_idx = am->token & 0xffffff;
3419 * Insert into the metadata tables all the info about the TypeBuilder tb.
3420 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3423 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3425 MonoDynamicTable *table;
3427 int i, is_object = 0, is_system = 0;
3430 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3431 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3432 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3433 n = mono_string_to_utf8 (tb->name);
3434 if (strcmp (n, "Object") == 0)
3436 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3438 n = mono_string_to_utf8 (tb->nspace);
3439 if (strcmp (n, "System") == 0)
3441 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3443 if (tb->parent && !(is_system && is_object) &&
3444 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3445 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3447 values [MONO_TYPEDEF_EXTENDS] = 0;
3449 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3450 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3453 * if we have explicitlayout or sequentiallayouts, output data in the
3454 * ClassLayout table.
3456 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3457 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3458 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3460 alloc_table (table, table->rows);
3461 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3462 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3463 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3464 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3467 /* handle interfaces */
3468 if (tb->interfaces) {
3469 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3471 table->rows += mono_array_length (tb->interfaces);
3472 alloc_table (table, table->rows);
3473 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3474 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3475 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3476 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3477 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3478 values += MONO_INTERFACEIMPL_SIZE;
3484 table = &assembly->tables [MONO_TABLE_FIELD];
3485 table->rows += tb->num_fields;
3486 alloc_table (table, table->rows);
3487 for (i = 0; i < tb->num_fields; ++i)
3488 mono_image_get_field_info (
3489 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3492 /* handle constructors */
3494 table = &assembly->tables [MONO_TABLE_METHOD];
3495 table->rows += mono_array_length (tb->ctors);
3496 alloc_table (table, table->rows);
3497 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3498 mono_image_get_ctor_info (domain,
3499 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3502 /* handle methods */
3504 table = &assembly->tables [MONO_TABLE_METHOD];
3505 table->rows += tb->num_methods;
3506 alloc_table (table, table->rows);
3507 for (i = 0; i < tb->num_methods; ++i)
3508 mono_image_get_method_info (
3509 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3512 /* Do the same with properties etc.. */
3513 if (tb->events && mono_array_length (tb->events)) {
3514 table = &assembly->tables [MONO_TABLE_EVENT];
3515 table->rows += mono_array_length (tb->events);
3516 alloc_table (table, table->rows);
3517 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3519 alloc_table (table, table->rows);
3520 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3521 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3522 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3523 for (i = 0; i < mono_array_length (tb->events); ++i)
3524 mono_image_get_event_info (
3525 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3527 if (tb->properties && mono_array_length (tb->properties)) {
3528 table = &assembly->tables [MONO_TABLE_PROPERTY];
3529 table->rows += mono_array_length (tb->properties);
3530 alloc_table (table, table->rows);
3531 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3533 alloc_table (table, table->rows);
3534 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3535 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3536 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3537 for (i = 0; i < mono_array_length (tb->properties); ++i)
3538 mono_image_get_property_info (
3539 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3542 /* handle generic parameters */
3543 if (tb->generic_params) {
3544 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3545 table->rows += mono_array_length (tb->generic_params);
3546 alloc_table (table, table->rows);
3547 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3548 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3550 mono_image_get_generic_param_info (
3551 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3555 mono_image_add_decl_security (assembly,
3556 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3559 MonoDynamicTable *ntable;
3561 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3562 ntable->rows += mono_array_length (tb->subtypes);
3563 alloc_table (ntable, ntable->rows);
3564 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3566 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3567 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3569 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3570 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3571 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3572 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3573 mono_string_to_utf8 (tb->name), tb->table_idx,
3574 ntable->next_idx, ntable->rows);*/
3575 values += MONO_NESTED_CLASS_SIZE;
3583 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3587 mono_ptr_array_append (*types, type);
3589 if (!type->subtypes)
3592 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3593 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3594 collect_types (types, subtype);
3599 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3601 if ((*type1)->table_idx < (*type2)->table_idx)
3604 if ((*type1)->table_idx > (*type2)->table_idx)
3611 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3616 for (i = 0; i < mono_array_length (pinfo); ++i) {
3617 MonoReflectionParamBuilder *pb;
3618 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3621 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3626 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3629 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3631 for (i = 0; i < tb->num_fields; ++i) {
3632 MonoReflectionFieldBuilder* fb;
3633 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3634 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3638 for (i = 0; i < mono_array_length (tb->events); ++i) {
3639 MonoReflectionEventBuilder* eb;
3640 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3641 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3644 if (tb->properties) {
3645 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3646 MonoReflectionPropertyBuilder* pb;
3647 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3648 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3652 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3653 MonoReflectionCtorBuilder* cb;
3654 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3655 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3656 params_add_cattrs (assembly, cb->pinfo);
3661 for (i = 0; i < tb->num_methods; ++i) {
3662 MonoReflectionMethodBuilder* mb;
3663 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3664 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3665 params_add_cattrs (assembly, mb->pinfo);
3670 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3671 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3676 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3680 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3682 if (moduleb->global_methods) {
3683 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3684 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3685 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3686 params_add_cattrs (assembly, mb->pinfo);
3690 if (moduleb->global_fields) {
3691 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3692 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3693 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3697 if (moduleb->types) {
3698 for (i = 0; i < moduleb->num_types; ++i)
3699 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3704 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3706 MonoDynamicTable *table;
3710 char *b = blob_size;
3713 table = &assembly->tables [MONO_TABLE_FILE];
3715 alloc_table (table, table->rows);
3716 values = table->values + table->next_idx * MONO_FILE_SIZE;
3717 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3718 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3719 if (image_is_dynamic (module->image)) {
3720 /* This depends on the fact that the main module is emitted last */
3721 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3722 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3725 path = g_strdup (module->image->name);
3727 mono_sha1_get_digest_from_file (path, hash);
3730 mono_metadata_encode_value (20, b, &b);
3731 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3732 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3737 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3739 MonoDynamicTable *table;
3742 table = &assembly->tables [MONO_TABLE_MODULE];
3743 mb->table_idx = table->next_idx ++;
3744 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3745 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3748 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3749 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3750 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3751 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3755 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3756 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3758 MonoDynamicTable *table;
3762 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3763 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3766 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3768 alloc_table (table, table->rows);
3769 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3771 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3772 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3773 if (klass->nested_in)
3774 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3776 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3777 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3778 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3780 res = table->next_idx;
3784 /* Emit nested types */
3785 if (klass->ext && klass->ext->nested_classes) {
3788 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3789 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3796 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3797 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3802 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3804 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3806 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3807 parent_index, assembly);
3811 * We need to do this ourselves since klass->nested_classes is not set up.
3814 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3815 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3820 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3821 guint32 module_index, MonoDynamicImage *assembly)
3823 MonoImage *image = module->image;
3827 t = &image->tables [MONO_TABLE_TYPEDEF];
3829 for (i = 0; i < t->rows; ++i) {
3831 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3832 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3834 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3835 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3840 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3842 MonoDynamicTable *table;
3844 guint32 scope, scope_idx, impl, current_idx;
3845 gboolean forwarder = TRUE;
3846 gpointer iter = NULL;
3849 if (klass->nested_in) {
3850 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3853 scope = resolution_scope_from_image (assembly, klass->image);
3854 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3855 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3856 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3859 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3862 alloc_table (table, table->rows);
3863 current_idx = table->next_idx;
3864 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3866 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3867 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3868 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3869 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3870 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3874 while ((nested = mono_class_get_nested_types (klass, &iter)))
3875 add_exported_type (assemblyb, assembly, nested, current_idx);
3879 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3884 if (!assemblyb->type_forwarders)
3887 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3888 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3893 type = mono_reflection_type_get_handle (t);
3896 klass = mono_class_from_mono_type (type);
3898 add_exported_type (assemblyb, assembly, klass, 0);
3902 #define align_pointer(base,p)\
3904 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3906 (p) += 4 - (__diff & 3);\
3910 compare_constants (const void *a, const void *b)
3912 const guint32 *a_values = a;
3913 const guint32 *b_values = b;
3914 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3918 compare_semantics (const void *a, const void *b)
3920 const guint32 *a_values = a;
3921 const guint32 *b_values = b;
3922 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3925 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3929 compare_custom_attrs (const void *a, const void *b)
3931 const guint32 *a_values = a;
3932 const guint32 *b_values = b;
3934 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3938 compare_field_marshal (const void *a, const void *b)
3940 const guint32 *a_values = a;
3941 const guint32 *b_values = b;
3943 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3947 compare_nested (const void *a, const void *b)
3949 const guint32 *a_values = a;
3950 const guint32 *b_values = b;
3952 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3956 compare_genericparam (const void *a, const void *b)
3958 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3959 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3961 if ((*b_entry)->owner == (*a_entry)->owner)
3963 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3964 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3966 return (*a_entry)->owner - (*b_entry)->owner;
3970 compare_declsecurity_attrs (const void *a, const void *b)
3972 const guint32 *a_values = a;
3973 const guint32 *b_values = b;
3975 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3979 compare_interface_impl (const void *a, const void *b)
3981 const guint32 *a_values = a;
3982 const guint32 *b_values = b;
3984 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3988 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3992 pad_heap (MonoDynamicStream *sh)
3994 if (sh->index & 3) {
3995 int sz = 4 - (sh->index & 3);
3996 memset (sh->data + sh->index, 0, sz);
4003 MonoDynamicStream *stream;
4007 * build_compressed_metadata() fills in the blob of data that represents the
4008 * raw metadata as it will be saved in the PE file. The five streams are output
4009 * and the metadata tables are comnpressed from the guint32 array representation,
4010 * to the compressed on-disk format.
4013 build_compressed_metadata (MonoDynamicImage *assembly)
4015 MonoDynamicTable *table;
4017 guint64 valid_mask = 0;
4018 guint64 sorted_mask;
4019 guint32 heapt_size = 0;
4020 guint32 meta_size = 256; /* allow for header and other stuff */
4021 guint32 table_offset;
4022 guint32 ntables = 0;
4028 struct StreamDesc stream_desc [5];
4030 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4031 for (i = 0; i < assembly->gen_params->len; i++){
4032 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4033 write_generic_param_entry (assembly, entry);
4036 stream_desc [0].name = "#~";
4037 stream_desc [0].stream = &assembly->tstream;
4038 stream_desc [1].name = "#Strings";
4039 stream_desc [1].stream = &assembly->sheap;
4040 stream_desc [2].name = "#US";
4041 stream_desc [2].stream = &assembly->us;
4042 stream_desc [3].name = "#Blob";
4043 stream_desc [3].stream = &assembly->blob;
4044 stream_desc [4].name = "#GUID";
4045 stream_desc [4].stream = &assembly->guid;
4047 /* tables that are sorted */
4048 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4049 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4050 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4051 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4052 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4053 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4054 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4056 /* Compute table sizes */
4057 /* the MonoImage has already been created in mono_image_basic_init() */
4058 meta = &assembly->image;
4060 /* sizes should be multiple of 4 */
4061 pad_heap (&assembly->blob);
4062 pad_heap (&assembly->guid);
4063 pad_heap (&assembly->sheap);
4064 pad_heap (&assembly->us);
4066 /* Setup the info used by compute_sizes () */
4067 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4068 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4069 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4071 meta_size += assembly->blob.index;
4072 meta_size += assembly->guid.index;
4073 meta_size += assembly->sheap.index;
4074 meta_size += assembly->us.index;
4076 for (i=0; i < MONO_TABLE_NUM; ++i)
4077 meta->tables [i].rows = assembly->tables [i].rows;
4079 for (i = 0; i < MONO_TABLE_NUM; i++){
4080 if (meta->tables [i].rows == 0)
4082 valid_mask |= (guint64)1 << i;
4084 meta->tables [i].row_size = mono_metadata_compute_size (
4085 meta, i, &meta->tables [i].size_bitfield);
4086 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4088 heapt_size += 24; /* #~ header size */
4089 heapt_size += ntables * 4;
4090 /* make multiple of 4 */
4093 meta_size += heapt_size;
4094 meta->raw_metadata = g_malloc0 (meta_size);
4095 p = (unsigned char*)meta->raw_metadata;
4096 /* the metadata signature */
4097 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4098 /* version numbers and 4 bytes reserved */
4099 int16val = (guint16*)p;
4100 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4101 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4103 /* version string */
4104 int32val = (guint32*)p;
4105 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4107 memcpy (p, meta->version, strlen (meta->version));
4108 p += GUINT32_FROM_LE (*int32val);
4109 align_pointer (meta->raw_metadata, p);
4110 int16val = (guint16*)p;
4111 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4112 *int16val = GUINT16_TO_LE (5); /* number of streams */
4116 * write the stream info.
4118 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4119 table_offset += 3; table_offset &= ~3;
4121 assembly->tstream.index = heapt_size;
4122 for (i = 0; i < 5; ++i) {
4123 int32val = (guint32*)p;
4124 stream_desc [i].stream->offset = table_offset;
4125 *int32val++ = GUINT32_TO_LE (table_offset);
4126 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4127 table_offset += GUINT32_FROM_LE (*int32val);
4128 table_offset += 3; table_offset &= ~3;
4130 strcpy ((char*)p, stream_desc [i].name);
4131 p += strlen (stream_desc [i].name) + 1;
4132 align_pointer (meta->raw_metadata, p);
4135 * now copy the data, the table stream header and contents goes first.
4137 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4138 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4139 int32val = (guint32*)p;
4140 *int32val = GUINT32_TO_LE (0); /* reserved */
4143 *p++ = 2; /* version */
4146 if (meta->idx_string_wide)
4148 if (meta->idx_guid_wide)
4150 if (meta->idx_blob_wide)
4153 *p++ = 1; /* reserved */
4154 int64val = (guint64*)p;
4155 *int64val++ = GUINT64_TO_LE (valid_mask);
4156 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4158 int32val = (guint32*)p;
4159 for (i = 0; i < MONO_TABLE_NUM; i++){
4160 if (meta->tables [i].rows == 0)
4162 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4164 p = (unsigned char*)int32val;
4166 /* sort the tables that still need sorting */
4167 table = &assembly->tables [MONO_TABLE_CONSTANT];
4169 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4170 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4172 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4173 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4175 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4176 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4178 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4179 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4181 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4182 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4183 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4185 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4186 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4188 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4190 /* compress the tables */
4191 for (i = 0; i < MONO_TABLE_NUM; i++){
4194 guint32 bitfield = meta->tables [i].size_bitfield;
4195 if (!meta->tables [i].rows)
4197 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4198 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4199 meta->tables [i].base = (char*)p;
4200 for (row = 1; row <= meta->tables [i].rows; ++row) {
4201 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4202 for (col = 0; col < assembly->tables [i].columns; ++col) {
4203 switch (mono_metadata_table_size (bitfield, col)) {
4205 *p++ = values [col];
4208 *p++ = values [col] & 0xff;
4209 *p++ = (values [col] >> 8) & 0xff;
4212 *p++ = values [col] & 0xff;
4213 *p++ = (values [col] >> 8) & 0xff;
4214 *p++ = (values [col] >> 16) & 0xff;
4215 *p++ = (values [col] >> 24) & 0xff;
4218 g_assert_not_reached ();
4222 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4225 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4226 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4227 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4228 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4229 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4231 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4235 * Some tables in metadata need to be sorted according to some criteria, but
4236 * when methods and fields are first created with reflection, they may be assigned a token
4237 * that doesn't correspond to the final token they will get assigned after the sorting.
4238 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4239 * with the reflection objects that represent them. Once all the tables are set up, the
4240 * reflection objects will contains the correct table index. fixup_method() will fixup the
4241 * tokens for the method with ILGenerator @ilgen.
4244 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4246 guint32 code_idx = GPOINTER_TO_UINT (value);
4247 MonoReflectionILTokenInfo *iltoken;
4248 MonoReflectionFieldBuilder *field;
4249 MonoReflectionCtorBuilder *ctor;
4250 MonoReflectionMethodBuilder *method;
4251 MonoReflectionTypeBuilder *tb;
4252 MonoReflectionArrayMethod *am;
4254 unsigned char *target;
4256 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4257 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4258 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4259 switch (target [3]) {
4260 case MONO_TABLE_FIELD:
4261 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4262 field = (MonoReflectionFieldBuilder *)iltoken->member;
4263 idx = field->table_idx;
4264 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4265 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4266 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4268 g_assert_not_reached ();
4271 case MONO_TABLE_METHOD:
4272 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4273 method = (MonoReflectionMethodBuilder *)iltoken->member;
4274 idx = method->table_idx;
4275 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4276 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4277 idx = ctor->table_idx;
4278 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4279 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4280 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4283 g_assert_not_reached ();
4286 case MONO_TABLE_TYPEDEF:
4287 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4288 g_assert_not_reached ();
4289 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4290 idx = tb->table_idx;
4292 case MONO_TABLE_MEMBERREF:
4293 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4294 am = (MonoReflectionArrayMethod*)iltoken->member;
4295 idx = am->table_idx;
4296 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4297 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4298 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4299 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4300 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4301 g_assert (m->klass->generic_class || m->klass->generic_container);
4303 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4305 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4306 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4307 g_assert (is_field_on_inst (f));
4309 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4310 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4312 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4314 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4316 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4319 g_assert_not_reached ();
4322 case MONO_TABLE_METHODSPEC:
4323 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4324 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4325 g_assert (mono_method_signature (m)->generic_param_count);
4327 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4329 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4332 g_assert_not_reached ();
4336 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4338 target [0] = idx & 0xff;
4339 target [1] = (idx >> 8) & 0xff;
4340 target [2] = (idx >> 16) & 0xff;
4347 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4348 * value is not known when the table is emitted.
4351 fixup_cattrs (MonoDynamicImage *assembly)
4353 MonoDynamicTable *table;
4355 guint32 type, i, idx, token;
4358 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4360 for (i = 0; i < table->rows; ++i) {
4361 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4363 type = values [MONO_CUSTOM_ATTR_TYPE];
4364 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4365 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4366 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4367 ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4370 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4371 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4372 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4373 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4374 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4375 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4376 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4377 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4384 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4386 MonoDynamicTable *table;
4389 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4391 alloc_table (table, table->rows);
4392 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4393 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4394 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4395 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4396 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4401 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4403 MonoDynamicTable *table;
4407 char *b = blob_size;
4409 guint32 idx, offset;
4411 if (rsrc->filename) {
4412 name = mono_string_to_utf8 (rsrc->filename);
4413 sname = g_path_get_basename (name);
4415 table = &assembly->tables [MONO_TABLE_FILE];
4417 alloc_table (table, table->rows);
4418 values = table->values + table->next_idx * MONO_FILE_SIZE;
4419 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4420 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4423 mono_sha1_get_digest_from_file (name, hash);
4424 mono_metadata_encode_value (20, b, &b);
4425 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4426 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4428 idx = table->next_idx++;
4430 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4436 data = mono_array_addr (rsrc->data, char, 0);
4437 len = mono_array_length (rsrc->data);
4443 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4444 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4445 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4446 mono_image_add_stream_data (&assembly->resources, data, len);
4450 * The entry should be emitted into the MANIFESTRESOURCE table of
4451 * the main module, but that needs to reference the FILE table
4452 * which isn't emitted yet.
4459 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4463 set_version_from_string (MonoString *version, guint32 *values)
4465 gchar *ver, *p, *str;
4468 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4469 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4470 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4471 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4474 ver = str = mono_string_to_utf8 (version);
4475 for (i = 0; i < 4; ++i) {
4476 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4482 /* handle Revision and Build */
4492 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4496 char *b = blob_size;
4501 len = mono_array_length (pkey);
4502 mono_metadata_encode_value (len, b, &b);
4503 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4504 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4506 assembly->public_key = g_malloc (len);
4507 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4508 assembly->public_key_len = len;
4510 /* Special case: check for ECMA key (16 bytes) */
4511 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4512 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4513 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4514 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4515 /* minimum key size (in 2.0) is 384 bits */
4516 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4518 /* FIXME - verifier */
4519 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4520 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4522 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4528 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4530 MonoDynamicTable *table;
4531 MonoDynamicImage *assembly;
4532 MonoReflectionAssemblyBuilder *assemblyb;
4536 guint32 module_index;
4538 assemblyb = moduleb->assemblyb;
4539 assembly = moduleb->dynamic_image;
4540 domain = mono_object_domain (assemblyb);
4542 /* Emit ASSEMBLY table */
4543 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4544 alloc_table (table, 1);
4545 values = table->values + MONO_ASSEMBLY_SIZE;
4546 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4547 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4548 if (assemblyb->culture) {
4549 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4551 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4553 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4554 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4555 set_version_from_string (assemblyb->version, values);
4557 /* Emit FILE + EXPORTED_TYPE table */
4559 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4561 MonoReflectionModuleBuilder *file_module =
4562 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4563 if (file_module != moduleb) {
4564 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4566 if (file_module->types) {
4567 for (j = 0; j < file_module->num_types; ++j) {
4568 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4569 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4574 if (assemblyb->loaded_modules) {
4575 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4576 MonoReflectionModule *file_module =
4577 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4578 mono_image_fill_file_table (domain, file_module, assembly);
4580 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4583 if (assemblyb->type_forwarders)
4584 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4586 /* Emit MANIFESTRESOURCE table */
4588 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4590 MonoReflectionModuleBuilder *file_module =
4591 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4592 /* The table for the main module is emitted later */
4593 if (file_module != moduleb) {
4595 if (file_module->resources) {
4596 int len = mono_array_length (file_module->resources);
4597 for (j = 0; j < len; ++j) {
4598 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4599 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4606 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4609 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4610 * for the modulebuilder @moduleb.
4611 * At the end of the process, method and field tokens are fixed up and the
4612 * on-disk compressed metadata representation is created.
4615 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4617 MonoDynamicTable *table;
4618 MonoDynamicImage *assembly;
4619 MonoReflectionAssemblyBuilder *assemblyb;
4625 assemblyb = moduleb->assemblyb;
4626 assembly = moduleb->dynamic_image;
4627 domain = mono_object_domain (assemblyb);
4629 if (assembly->text_rva)
4632 assembly->text_rva = START_TEXT_RVA;
4634 if (moduleb->is_main) {
4635 mono_image_emit_manifest (moduleb);
4638 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4639 table->rows = 1; /* .<Module> */
4641 alloc_table (table, table->rows);
4643 * Set the first entry.
4645 values = table->values + table->columns;
4646 values [MONO_TYPEDEF_FLAGS] = 0;
4647 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4648 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4649 values [MONO_TYPEDEF_EXTENDS] = 0;
4650 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4651 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4654 * handle global methods
4655 * FIXME: test what to do when global methods are defined in multiple modules.
4657 if (moduleb->global_methods) {
4658 table = &assembly->tables [MONO_TABLE_METHOD];
4659 table->rows += mono_array_length (moduleb->global_methods);
4660 alloc_table (table, table->rows);
4661 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4662 mono_image_get_method_info (
4663 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4665 if (moduleb->global_fields) {
4666 table = &assembly->tables [MONO_TABLE_FIELD];
4667 table->rows += mono_array_length (moduleb->global_fields);
4668 alloc_table (table, table->rows);
4669 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4670 mono_image_get_field_info (
4671 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4674 table = &assembly->tables [MONO_TABLE_MODULE];
4675 alloc_table (table, 1);
4676 mono_image_fill_module_table (domain, moduleb, assembly);
4678 /* Collect all types into a list sorted by their table_idx */
4679 mono_ptr_array_init (types, moduleb->num_types);
4682 for (i = 0; i < moduleb->num_types; ++i) {
4683 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4684 collect_types (&types, type);
4687 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4688 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4689 table->rows += mono_ptr_array_size (types);
4690 alloc_table (table, table->rows);
4693 * Emit type names + namespaces at one place inside the string heap,
4694 * so load_class_names () needs to touch fewer pages.
4696 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4697 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4698 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4700 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4701 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4702 string_heap_insert_mstring (&assembly->sheap, tb->name);
4705 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4706 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4707 mono_image_get_type_info (domain, type, assembly);
4711 * table->rows is already set above and in mono_image_fill_module_table.
4713 /* add all the custom attributes at the end, once all the indexes are stable */
4714 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4716 /* CAS assembly permissions */
4717 if (assemblyb->permissions_minimum)
4718 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4719 if (assemblyb->permissions_optional)
4720 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4721 if (assemblyb->permissions_refused)
4722 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4724 module_add_cattrs (assembly, moduleb);
4727 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4729 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4730 * the final tokens and don't need another fixup pass. */
4732 if (moduleb->global_methods) {
4733 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4734 MonoReflectionMethodBuilder *mb = mono_array_get (
4735 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4736 mono_image_add_methodimpl (assembly, mb);
4740 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4741 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4742 if (type->methods) {
4743 for (j = 0; j < type->num_methods; ++j) {
4744 MonoReflectionMethodBuilder *mb = mono_array_get (
4745 type->methods, MonoReflectionMethodBuilder*, j);
4747 mono_image_add_methodimpl (assembly, mb);
4752 mono_ptr_array_destroy (types);
4754 fixup_cattrs (assembly);
4757 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4760 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4762 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4765 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4769 guint32 import_lookup_table;
4773 guint32 import_address_table_rva;
4781 #ifndef DISABLE_REFLECTION_EMIT
4784 * mono_image_insert_string:
4785 * @module: module builder object
4788 * Insert @str into the user string stream of @module.
4791 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4793 MonoDynamicImage *assembly;
4798 if (!module->dynamic_image)
4799 mono_image_module_basic_init (module);
4801 assembly = module->dynamic_image;
4803 if (assembly->save) {
4804 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4805 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4806 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4808 char *swapped = g_malloc (2 * mono_string_length (str));
4809 const char *p = (const char*)mono_string_chars (str);
4811 swap_with_size (swapped, p, 2, mono_string_length (str));
4812 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4816 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4818 mono_image_add_stream_data (&assembly->us, "", 1);
4820 idx = assembly->us.index ++;
4823 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4825 return MONO_TOKEN_STRING | idx;
4829 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4833 MonoMethodSignature *sig;
4835 klass = obj->vtable->klass;
4836 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4837 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4838 MonoMethodSignature *old;
4839 guint32 sig_token, parent;
4842 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4844 nargs = mono_array_length (opt_param_types);
4845 old = mono_method_signature (method);
4846 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4848 sig->hasthis = old->hasthis;
4849 sig->explicit_this = old->explicit_this;
4850 sig->call_convention = old->call_convention;
4851 sig->generic_param_count = old->generic_param_count;
4852 sig->param_count = old->param_count + nargs;
4853 sig->sentinelpos = old->param_count;
4854 sig->ret = old->ret;
4856 for (i = 0; i < old->param_count; i++)
4857 sig->params [i] = old->params [i];
4859 for (i = 0; i < nargs; i++) {
4860 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4861 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4864 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4865 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4866 parent >>= MONO_TYPEDEFORREF_BITS;
4868 parent <<= MONO_MEMBERREF_PARENT_BITS;
4869 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4871 sig_token = method_encode_signature (assembly, sig);
4872 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4873 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4874 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4875 ReflectionMethodBuilder rmb;
4876 guint32 parent, sig_token;
4877 int nopt_args, nparams, ngparams, i;
4880 reflection_methodbuilder_from_method_builder (&rmb, mb);
4881 rmb.opt_types = opt_param_types;
4882 nopt_args = mono_array_length (opt_param_types);
4884 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4885 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4886 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4888 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4889 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4890 sig->call_convention = rmb.call_conv;
4891 sig->generic_param_count = ngparams;
4892 sig->param_count = nparams + nopt_args;
4893 sig->sentinelpos = nparams;
4894 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4896 for (i = 0; i < nparams; i++) {
4897 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4898 sig->params [i] = mono_reflection_type_get_handle (rt);
4901 for (i = 0; i < nopt_args; i++) {
4902 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4903 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4906 sig_token = method_builder_encode_signature (assembly, &rmb);
4908 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4909 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4911 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4912 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4914 name = mono_string_to_utf8 (rmb.name);
4915 token = mono_image_get_varargs_method_token (
4916 assembly, parent, name, sig_token);
4919 g_error ("requested method token for %s\n", klass->name);
4922 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4923 register_dyn_token (assembly, token, obj);
4928 * mono_image_create_token:
4929 * @assembly: a dynamic assembly
4931 * @register_token: Whenever to register the token in the assembly->tokens hash.
4933 * Get a token to insert in the IL code stream for the given MemberInfo.
4934 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4935 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4939 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4940 gboolean create_open_instance, gboolean register_token)
4945 klass = obj->vtable->klass;
4947 /* Check for user defined reflection objects */
4948 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4949 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4950 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4952 if (strcmp (klass->name, "MethodBuilder") == 0) {
4953 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4954 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4956 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4957 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4959 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4960 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4961 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4962 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4963 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4965 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4966 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4968 token = mono_image_get_ctorbuilder_token (assembly, mb);
4969 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4970 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4971 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4972 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4973 if (tb->generic_params) {
4974 token = mono_image_get_generic_field_token (assembly, fb);
4976 if (tb->module->dynamic_image == assembly) {
4977 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4979 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4982 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4983 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4984 if (create_open_instance && tb->generic_params) {
4986 init_type_builder_generics (obj);
4987 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4988 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4989 token = mono_metadata_token_from_dor (token);
4990 } else if (tb->module->dynamic_image == assembly) {
4991 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4994 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4995 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4997 } else if (strcmp (klass->name, "MonoType") == 0) {
4998 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4999 MonoClass *mc = mono_class_from_mono_type (type);
5000 token = mono_metadata_token_from_dor (
5001 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5002 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5003 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5004 token = mono_metadata_token_from_dor (
5005 mono_image_typedef_or_ref (assembly, type));
5006 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5007 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5008 token = mono_metadata_token_from_dor (
5009 mono_image_typedef_or_ref (assembly, type));
5010 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5011 strcmp (klass->name, "MonoMethod") == 0 ||
5012 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5013 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5014 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5015 if (m->method->is_inflated) {
5016 if (create_open_instance)
5017 token = mono_image_get_methodspec_token (assembly, m->method);
5019 token = mono_image_get_inflated_method_token (assembly, m->method);
5020 } else if ((m->method->klass->image == &assembly->image) &&
5021 !m->method->klass->generic_class) {
5022 static guint32 method_table_idx = 0xffffff;
5023 if (m->method->klass->wastypebuilder) {
5024 /* we use the same token as the one that was assigned
5025 * to the Methodbuilder.
5026 * FIXME: do the equivalent for Fields.
5028 token = m->method->token;
5031 * Each token should have a unique index, but the indexes are
5032 * assigned by managed code, so we don't know about them. An
5033 * easy solution is to count backwards...
5035 method_table_idx --;
5036 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5039 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5041 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5042 } else if (strcmp (klass->name, "MonoField") == 0) {
5043 MonoReflectionField *f = (MonoReflectionField *)obj;
5044 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5045 static guint32 field_table_idx = 0xffffff;
5047 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5049 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5051 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5052 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5053 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5054 token = mono_image_get_array_token (assembly, m);
5055 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5056 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5057 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5058 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5059 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5060 token = mono_metadata_token_from_dor (
5061 mono_image_typedef_or_ref (assembly, type));
5062 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5063 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5064 token = mono_image_get_field_on_inst_token (assembly, f);
5065 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5066 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5067 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5068 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5069 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5070 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5071 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5072 MonoReflectionType *type = (MonoReflectionType *)obj;
5073 token = mono_metadata_token_from_dor (
5074 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5076 g_error ("requested token for %s\n", klass->name);
5080 mono_image_register_token (assembly, token, obj);
5086 * mono_image_register_token:
5088 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5089 * the Module.ResolveXXXToken () methods to work.
5092 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5096 dynamic_image_lock (assembly);
5097 prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5099 /* There could be multiple MethodInfo objects with the same token */
5100 //g_assert (prev == obj);
5102 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5104 dynamic_image_unlock (assembly);
5107 static MonoDynamicImage*
5108 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5110 static const guchar entrycode [16] = {0xff, 0x25, 0};
5111 MonoDynamicImage *image;
5114 const char *version;
5116 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5117 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5119 version = mono_get_runtime_info ()->runtime_version;
5122 /* The MonoGHashTable's need GC tracking */
5123 image = GC_MALLOC (sizeof (MonoDynamicImage));
5125 image = g_new0 (MonoDynamicImage, 1);
5128 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5130 /*g_print ("created image %p\n", image);*/
5131 /* keep in sync with image.c */
5132 image->image.name = assembly_name;
5133 image->image.assembly_name = image->image.name; /* they may be different */
5134 image->image.module_name = module_name;
5135 image->image.version = g_strdup (version);
5136 image->image.md_version_major = 1;
5137 image->image.md_version_minor = 1;
5138 image->image.dynamic = TRUE;
5140 image->image.references = g_new0 (MonoAssembly*, 1);
5141 image->image.references [0] = NULL;
5143 mono_image_init (&image->image);
5145 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5146 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5147 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5148 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5149 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5150 image->handleref = g_hash_table_new (NULL, NULL);
5151 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5152 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5153 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5154 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5155 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5156 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5157 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5158 image->gen_params = g_ptr_array_new ();
5159 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5161 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5162 string_heap_init (&image->sheap);
5163 mono_image_add_stream_data (&image->us, "", 1);
5164 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5165 /* import tables... */
5166 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5167 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5168 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5169 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5170 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5171 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5172 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5173 stream_data_align (&image->code);
5175 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5177 for (i=0; i < MONO_TABLE_NUM; ++i) {
5178 image->tables [i].next_idx = 1;
5179 image->tables [i].columns = table_sizes [i];
5182 image->image.assembly = (MonoAssembly*)assembly;
5183 image->run = assembly->run;
5184 image->save = assembly->save;
5185 image->pe_kind = 0x1; /* ILOnly */
5186 image->machine = 0x14c; /* I386 */
5188 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5195 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5201 release_hashtable (MonoGHashTable **hash)
5204 mono_g_hash_table_destroy (*hash);
5210 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5212 release_hashtable (&image->token_fixups);
5213 release_hashtable (&image->handleref_managed);
5214 release_hashtable (&image->tokens);
5215 release_hashtable (&image->remapped_tokens);
5216 release_hashtable (&image->generic_def_objects);
5217 release_hashtable (&image->methodspec);
5221 mono_dynamic_image_free (MonoDynamicImage *image)
5223 MonoDynamicImage *di = image;
5228 mono_g_hash_table_destroy (di->methodspec);
5230 g_hash_table_destroy (di->typespec);
5232 g_hash_table_destroy (di->typeref);
5234 g_hash_table_destroy (di->handleref);
5235 if (di->handleref_managed)
5236 mono_g_hash_table_destroy (di->handleref_managed);
5238 mono_g_hash_table_destroy (di->tokens);
5239 if (di->remapped_tokens)
5240 mono_g_hash_table_destroy (di->remapped_tokens);
5241 if (di->generic_def_objects)
5242 mono_g_hash_table_destroy (di->generic_def_objects);
5243 if (di->blob_cache) {
5244 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5245 g_hash_table_destroy (di->blob_cache);
5247 if (di->standalonesig_cache)
5248 g_hash_table_destroy (di->standalonesig_cache);
5249 for (list = di->array_methods; list; list = list->next) {
5250 ArrayMethod *am = (ArrayMethod *)list->data;
5255 g_list_free (di->array_methods);
5256 if (di->gen_params) {
5257 for (i = 0; i < di->gen_params->len; i++) {
5258 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5259 mono_gc_deregister_root ((char*) &entry->gparam);
5262 g_ptr_array_free (di->gen_params, TRUE);
5264 if (di->token_fixups)
5265 mono_g_hash_table_destroy (di->token_fixups);
5266 if (di->method_to_table_idx)
5267 g_hash_table_destroy (di->method_to_table_idx);
5268 if (di->field_to_table_idx)
5269 g_hash_table_destroy (di->field_to_table_idx);
5270 if (di->method_aux_hash)
5271 g_hash_table_destroy (di->method_aux_hash);
5272 if (di->vararg_aux_hash)
5273 g_hash_table_destroy (di->vararg_aux_hash);
5274 g_free (di->strong_name);
5275 g_free (di->win32_res);
5277 g_free (di->public_key);
5279 /*g_print ("string heap destroy for image %p\n", di);*/
5280 mono_dynamic_stream_reset (&di->sheap);
5281 mono_dynamic_stream_reset (&di->code);
5282 mono_dynamic_stream_reset (&di->resources);
5283 mono_dynamic_stream_reset (&di->us);
5284 mono_dynamic_stream_reset (&di->blob);
5285 mono_dynamic_stream_reset (&di->tstream);
5286 mono_dynamic_stream_reset (&di->guid);
5287 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5288 g_free (di->tables [i].values);
5293 mono_dynamic_image_free_image (MonoDynamicImage *image)
5295 /* See create_dynamic_mono_image () */
5297 /* Allocated using GC_MALLOC */
5303 #ifndef DISABLE_REFLECTION_EMIT
5306 * mono_image_basic_init:
5307 * @assembly: an assembly builder object
5309 * Create the MonoImage that represents the assembly builder and setup some
5310 * of the helper hash table and the basic metadata streams.
5313 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5315 MonoDynamicAssembly *assembly;
5316 MonoDynamicImage *image;
5317 MonoDomain *domain = mono_object_domain (assemblyb);
5319 if (assemblyb->dynamic_assembly)
5323 /* assembly->assembly.image might be GC allocated */
5324 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5326 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5329 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5331 assembly->assembly.ref_count = 1;
5332 assembly->assembly.dynamic = TRUE;
5333 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5334 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5335 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5336 if (assemblyb->culture)
5337 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5339 assembly->assembly.aname.culture = g_strdup ("");
5341 if (assemblyb->version) {
5342 char *vstr = mono_string_to_utf8 (assemblyb->version);
5343 char **version = g_strsplit (vstr, ".", 4);
5344 char **parts = version;
5345 assembly->assembly.aname.major = atoi (*parts++);
5346 assembly->assembly.aname.minor = atoi (*parts++);
5347 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5348 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5350 g_strfreev (version);
5353 assembly->assembly.aname.major = 0;
5354 assembly->assembly.aname.minor = 0;
5355 assembly->assembly.aname.build = 0;
5356 assembly->assembly.aname.revision = 0;
5359 assembly->run = assemblyb->access != 2;
5360 assembly->save = assemblyb->access != 1;
5361 assembly->domain = domain;
5363 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5364 image->initial_image = TRUE;
5365 assembly->assembly.aname.name = image->image.name;
5366 assembly->assembly.image = &image->image;
5367 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5368 /* -1 to correct for the trailing NULL byte */
5369 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5370 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5372 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5375 mono_domain_assemblies_lock (domain);
5376 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5377 mono_domain_assemblies_unlock (domain);
5379 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5381 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5383 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5386 #endif /* !DISABLE_REFLECTION_EMIT */
5388 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5391 calc_section_size (MonoDynamicImage *assembly)
5395 /* alignment constraints */
5396 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5397 g_assert ((assembly->code.index % 4) == 0);
5398 assembly->meta_size += 3;
5399 assembly->meta_size &= ~3;
5400 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5401 g_assert ((assembly->resources.index % 4) == 0);
5403 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5404 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5407 if (assembly->win32_res) {
5408 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5410 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5411 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5415 assembly->sections [MONO_SECTION_RELOC].size = 12;
5416 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5426 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5430 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5432 ResTreeNode *t1 = (ResTreeNode*)a;
5433 ResTreeNode *t2 = (ResTreeNode*)b;
5435 return t1->id - t2->id;
5439 * resource_tree_create:
5441 * Organize the resources into a resource tree.
5443 static ResTreeNode *
5444 resource_tree_create (MonoArray *win32_resources)
5446 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5450 tree = g_new0 (ResTreeNode, 1);
5452 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5453 MonoReflectionWin32Resource *win32_res =
5454 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5458 /* FIXME: BUG: this stores managed references in unmanaged memory */
5459 lang_node = g_new0 (ResTreeNode, 1);
5460 lang_node->id = win32_res->lang_id;
5461 lang_node->win32_res = win32_res;
5463 /* Create type node if neccesary */
5465 for (l = tree->children; l; l = l->next)
5466 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5467 type_node = (ResTreeNode*)l->data;
5472 type_node = g_new0 (ResTreeNode, 1);
5473 type_node->id = win32_res->res_type;
5476 * The resource types have to be sorted otherwise
5477 * Windows Explorer can't display the version information.
5479 tree->children = g_slist_insert_sorted (tree->children,
5480 type_node, resource_tree_compare_by_id);
5483 /* Create res node if neccesary */
5485 for (l = type_node->children; l; l = l->next)
5486 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5487 res_node = (ResTreeNode*)l->data;
5492 res_node = g_new0 (ResTreeNode, 1);
5493 res_node->id = win32_res->res_id;
5494 type_node->children = g_slist_append (type_node->children, res_node);
5497 res_node->children = g_slist_append (res_node->children, lang_node);
5504 * resource_tree_encode:
5506 * Encode the resource tree into the format used in the PE file.
5509 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5512 MonoPEResourceDir dir;
5513 MonoPEResourceDirEntry dir_entry;
5514 MonoPEResourceDataEntry data_entry;
5516 guint32 res_id_entries;
5519 * For the format of the resource directory, see the article
5520 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5524 memset (&dir, 0, sizeof (dir));
5525 memset (&dir_entry, 0, sizeof (dir_entry));
5526 memset (&data_entry, 0, sizeof (data_entry));
5528 g_assert (sizeof (dir) == 16);
5529 g_assert (sizeof (dir_entry) == 8);
5530 g_assert (sizeof (data_entry) == 16);
5532 node->offset = p - begin;
5534 /* IMAGE_RESOURCE_DIRECTORY */
5535 res_id_entries = g_slist_length (node->children);
5536 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5538 memcpy (p, &dir, sizeof (dir));
5541 /* Reserve space for entries */
5543 p += sizeof (dir_entry) * res_id_entries;
5545 /* Write children */
5546 for (l = node->children; l; l = l->next) {
5547 ResTreeNode *child = (ResTreeNode*)l->data;
5549 if (child->win32_res) {
5552 child->offset = p - begin;
5554 /* IMAGE_RESOURCE_DATA_ENTRY */
5555 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5556 size = mono_array_length (child->win32_res->res_data);
5557 data_entry.rde_size = GUINT32_TO_LE (size);
5559 memcpy (p, &data_entry, sizeof (data_entry));
5560 p += sizeof (data_entry);
5562 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5565 resource_tree_encode (child, begin, p, &p);
5569 /* IMAGE_RESOURCE_ENTRY */
5570 for (l = node->children; l; l = l->next) {
5571 ResTreeNode *child = (ResTreeNode*)l->data;
5573 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5574 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5576 memcpy (entries, &dir_entry, sizeof (dir_entry));
5577 entries += sizeof (dir_entry);
5584 resource_tree_free (ResTreeNode * node)
5587 for (list = node->children; list; list = list->next)
5588 resource_tree_free ((ResTreeNode*)list->data);
5589 g_slist_free(node->children);
5594 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5599 MonoReflectionWin32Resource *win32_res;
5602 if (!assemblyb->win32_resources)
5606 * Resources are stored in a three level tree inside the PE file.
5607 * - level one contains a node for each type of resource
5608 * - level two contains a node for each resource
5609 * - level three contains a node for each instance of a resource for a
5610 * specific language.
5613 tree = resource_tree_create (assemblyb->win32_resources);
5615 /* Estimate the size of the encoded tree */
5617 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5618 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5619 size += mono_array_length (win32_res->res_data);
5621 /* Directory structure */
5622 size += mono_array_length (assemblyb->win32_resources) * 256;
5623 p = buf = g_malloc (size);
5625 resource_tree_encode (tree, p, p, &p);
5627 g_assert (p - buf <= size);
5629 assembly->win32_res = g_malloc (p - buf);
5630 assembly->win32_res_size = p - buf;
5631 memcpy (assembly->win32_res, buf, p - buf);
5634 resource_tree_free (tree);
5638 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5640 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5643 p += sizeof (MonoPEResourceDir);
5644 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5645 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5646 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5647 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5648 fixup_resource_directory (res_section, child, rva);
5650 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5651 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5654 p += sizeof (MonoPEResourceDirEntry);
5659 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5662 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5663 g_error ("WriteFile returned %d\n", GetLastError ());
5667 * mono_image_create_pefile:
5668 * @mb: a module builder object
5670 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5671 * assembly->pefile where it can be easily retrieved later in chunks.
5674 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5676 MonoMSDOSHeader *msdos;
5677 MonoDotNetHeader *header;
5678 MonoSectionTable *section;
5679 MonoCLIHeader *cli_header;
5680 guint32 size, image_size, virtual_base, text_offset;
5681 guint32 header_start, section_start, file_offset, virtual_offset;
5682 MonoDynamicImage *assembly;
5683 MonoReflectionAssemblyBuilder *assemblyb;
5684 MonoDynamicStream pefile_stream = {0};
5685 MonoDynamicStream *pefile = &pefile_stream;
5687 guint32 *rva, value;
5689 static const unsigned char msheader[] = {
5690 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5691 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5694 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5695 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5696 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5697 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5700 assemblyb = mb->assemblyb;
5702 mono_image_basic_init (assemblyb);
5703 assembly = mb->dynamic_image;
5705 assembly->pe_kind = assemblyb->pe_kind;
5706 assembly->machine = assemblyb->machine;
5707 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5708 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5710 mono_image_build_metadata (mb);
5712 if (mb->is_main && assemblyb->resources) {
5713 int len = mono_array_length (assemblyb->resources);
5714 for (i = 0; i < len; ++i)
5715 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5718 if (mb->resources) {
5719 int len = mono_array_length (mb->resources);
5720 for (i = 0; i < len; ++i)
5721 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5724 build_compressed_metadata (assembly);
5727 assembly_add_win32_resources (assembly, assemblyb);
5729 nsections = calc_section_size (assembly);
5731 /* The DOS header and stub */
5732 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5733 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5735 /* the dotnet header */
5736 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5738 /* the section tables */
5739 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5741 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5742 virtual_offset = VIRT_ALIGN;
5745 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5746 if (!assembly->sections [i].size)
5749 file_offset += FILE_ALIGN - 1;
5750 file_offset &= ~(FILE_ALIGN - 1);
5751 virtual_offset += VIRT_ALIGN - 1;
5752 virtual_offset &= ~(VIRT_ALIGN - 1);
5754 assembly->sections [i].offset = file_offset;
5755 assembly->sections [i].rva = virtual_offset;
5757 file_offset += assembly->sections [i].size;
5758 virtual_offset += assembly->sections [i].size;
5759 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5762 file_offset += FILE_ALIGN - 1;
5763 file_offset &= ~(FILE_ALIGN - 1);
5765 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5767 /* back-patch info */
5768 msdos = (MonoMSDOSHeader*)pefile->data;
5769 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5771 header = (MonoDotNetHeader*)(pefile->data + header_start);
5772 header->pesig [0] = 'P';
5773 header->pesig [1] = 'E';
5775 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5776 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5777 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5778 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5779 if (assemblyb->pekind == 1) {
5781 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5784 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5787 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5789 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5790 header->pe.pe_major = 6;
5791 header->pe.pe_minor = 0;
5792 size = assembly->sections [MONO_SECTION_TEXT].size;
5793 size += FILE_ALIGN - 1;
5794 size &= ~(FILE_ALIGN - 1);
5795 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5796 size = assembly->sections [MONO_SECTION_RSRC].size;
5797 size += FILE_ALIGN - 1;
5798 size &= ~(FILE_ALIGN - 1);
5799 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5800 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5801 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5802 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5803 /* pe_rva_entry_point always at the beginning of the text section */
5804 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5806 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5807 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5808 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5809 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5810 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5811 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5812 size = section_start;
5813 size += FILE_ALIGN - 1;
5814 size &= ~(FILE_ALIGN - 1);
5815 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5817 size += VIRT_ALIGN - 1;
5818 size &= ~(VIRT_ALIGN - 1);
5819 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5822 // Translate the PEFileKind value to the value expected by the Windows loader
5828 // PEFileKinds.Dll == 1
5829 // PEFileKinds.ConsoleApplication == 2
5830 // PEFileKinds.WindowApplication == 3
5833 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5834 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5836 if (assemblyb->pekind == 3)
5841 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5843 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5844 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5845 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5846 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5847 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5848 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5850 /* fill data directory entries */
5852 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5853 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5855 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5856 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5858 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5859 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5860 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5861 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5862 /* patch entrypoint name */
5863 if (assemblyb->pekind == 1)
5864 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5866 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5867 /* patch imported function RVA name */
5868 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5869 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5871 /* the import table */
5872 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5873 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5874 /* patch imported dll RVA name and other entries in the dir */
5875 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5876 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5877 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5878 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5879 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5880 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5882 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5883 value = (assembly->text_rva + assembly->imp_names_offset);
5884 *p++ = (value) & 0xff;
5885 *p++ = (value >> 8) & (0xff);
5886 *p++ = (value >> 16) & (0xff);
5887 *p++ = (value >> 24) & (0xff);
5889 /* the CLI header info */
5890 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5891 cli_header->ch_size = GUINT32_FROM_LE (72);
5892 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5893 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5894 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5895 if (assemblyb->entry_point) {
5896 guint32 table_idx = 0;
5897 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5898 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5899 table_idx = methodb->table_idx;
5901 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5903 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5905 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5907 /* The embedded managed resources */
5908 text_offset = assembly->text_rva + assembly->code.index;
5909 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5910 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5911 text_offset += assembly->resources.index;
5912 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5913 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5914 text_offset += assembly->meta_size;
5915 if (assembly->strong_name_size) {
5916 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5917 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5918 text_offset += assembly->strong_name_size;
5921 /* write the section tables and section content */
5922 section = (MonoSectionTable*)(pefile->data + section_start);
5923 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5924 static const char section_names [][7] = {
5925 ".text", ".rsrc", ".reloc"
5927 if (!assembly->sections [i].size)
5929 strcpy (section->st_name, section_names [i]);
5930 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5931 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5932 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5933 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5934 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5935 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5936 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5940 checked_write_file (file, pefile->data, pefile->index);
5942 mono_dynamic_stream_reset (pefile);
5944 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5945 if (!assembly->sections [i].size)
5948 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5949 g_error ("SetFilePointer returned %d\n", GetLastError ());
5952 case MONO_SECTION_TEXT:
5953 /* patch entry point */
5954 p = (guchar*)(assembly->code.data + 2);
5955 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5956 *p++ = (value) & 0xff;
5957 *p++ = (value >> 8) & 0xff;
5958 *p++ = (value >> 16) & 0xff;
5959 *p++ = (value >> 24) & 0xff;
5961 checked_write_file (file, assembly->code.data, assembly->code.index);
5962 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5963 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5964 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5967 g_free (assembly->image.raw_metadata);
5969 case MONO_SECTION_RELOC: {
5973 guint16 type_and_offset;
5977 g_assert (sizeof (reloc) == 12);
5979 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5980 reloc.block_size = GUINT32_FROM_LE (12);
5983 * the entrypoint is always at the start of the text section
5984 * 3 is IMAGE_REL_BASED_HIGHLOW
5985 * 2 is patch_size_rva - text_rva
5987 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5990 checked_write_file (file, &reloc, sizeof (reloc));
5994 case MONO_SECTION_RSRC:
5995 if (assembly->win32_res) {
5997 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5998 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5999 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6003 g_assert_not_reached ();
6007 /* check that the file is properly padded */
6008 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6009 g_error ("SetFilePointer returned %d\n", GetLastError ());
6010 if (! SetEndOfFile (file))
6011 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6013 mono_dynamic_stream_reset (&assembly->code);
6014 mono_dynamic_stream_reset (&assembly->us);
6015 mono_dynamic_stream_reset (&assembly->blob);
6016 mono_dynamic_stream_reset (&assembly->guid);
6017 mono_dynamic_stream_reset (&assembly->sheap);
6019 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6020 g_hash_table_destroy (assembly->blob_cache);
6021 assembly->blob_cache = NULL;
6024 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6027 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6029 g_assert_not_reached ();
6032 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6034 #ifndef DISABLE_REFLECTION_EMIT
6036 MonoReflectionModule *
6037 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6041 MonoImageOpenStatus status;
6042 MonoDynamicAssembly *assembly;
6043 guint32 module_count;
6044 MonoImage **new_modules;
6045 gboolean *new_modules_loaded;
6047 name = mono_string_to_utf8 (fileName);
6049 image = mono_image_open (name, &status);
6052 if (status == MONO_IMAGE_ERROR_ERRNO)
6053 exc = mono_get_exception_file_not_found (fileName);
6055 exc = mono_get_exception_bad_image_format (name);
6057 mono_raise_exception (exc);
6062 assembly = ab->dynamic_assembly;
6063 image->assembly = (MonoAssembly*)assembly;
6065 module_count = image->assembly->image->module_count;
6066 new_modules = g_new0 (MonoImage *, module_count + 1);
6067 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6069 if (image->assembly->image->modules)
6070 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6071 if (image->assembly->image->modules_loaded)
6072 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6073 new_modules [module_count] = image;
6074 new_modules_loaded [module_count] = TRUE;
6075 mono_image_addref (image);
6077 g_free (image->assembly->image->modules);
6078 image->assembly->image->modules = new_modules;
6079 image->assembly->image->modules_loaded = new_modules_loaded;
6080 image->assembly->image->module_count ++;
6082 mono_assembly_load_references (image, &status);
6084 mono_image_close (image);
6085 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6088 return mono_module_get_object (mono_domain_get (), image);
6091 #endif /* DISABLE_REFLECTION_EMIT */
6094 * We need to return always the same object for MethodInfo, FieldInfo etc..
6095 * but we need to consider the reflected type.
6096 * type uses a different hash, since it uses custom hash/equal functions.
6101 MonoClass *refclass;
6105 reflected_equal (gconstpointer a, gconstpointer b) {
6106 const ReflectedEntry *ea = a;
6107 const ReflectedEntry *eb = b;
6109 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6113 reflected_hash (gconstpointer a) {
6114 const ReflectedEntry *ea = a;
6115 return mono_aligned_addr_hash (ea->item);
6118 #define CHECK_OBJECT(t,p,k) \
6124 mono_domain_lock (domain); \
6125 if (!domain->refobject_hash) \
6126 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6127 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6128 mono_domain_unlock (domain); \
6131 mono_domain_unlock (domain); \
6134 #ifdef HAVE_BOEHM_GC
6135 /* ReflectedEntry doesn't need to be GC tracked */
6136 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6137 #define FREE_REFENTRY(entry) g_free ((entry))
6138 #define REFENTRY_REQUIRES_CLEANUP
6140 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6142 #define FREE_REFENTRY(entry)
6145 #define CACHE_OBJECT(t,p,o,k) \
6148 ReflectedEntry pe; \
6150 pe.refclass = (k); \
6151 mono_domain_lock (domain); \
6152 if (!domain->refobject_hash) \
6153 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6154 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6156 ReflectedEntry *e = ALLOC_REFENTRY; \
6158 e->refclass = (k); \
6159 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6162 mono_domain_unlock (domain); \
6167 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6169 mono_domain_lock (domain);
6170 if (domain->refobject_hash) {
6172 gpointer orig_pe, orig_value;
6175 pe.refclass = klass;
6176 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6177 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6178 FREE_REFENTRY (orig_pe);
6181 mono_domain_unlock (domain);
6184 #ifdef REFENTRY_REQUIRES_CLEANUP
6186 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6188 FREE_REFENTRY (key);
6193 mono_reflection_cleanup_domain (MonoDomain *domain)
6195 if (domain->refobject_hash) {
6196 /*let's avoid scanning the whole hashtable if not needed*/
6197 #ifdef REFENTRY_REQUIRES_CLEANUP
6198 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6200 mono_g_hash_table_destroy (domain->refobject_hash);
6201 domain->refobject_hash = NULL;
6205 #ifndef DISABLE_REFLECTION_EMIT
6207 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6209 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6213 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6215 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6219 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6221 MonoDynamicImage *image = moduleb->dynamic_image;
6222 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6226 MonoImage **new_modules;
6228 char *name, *fqname;
6230 * FIXME: we already created an image in mono_image_basic_init (), but
6231 * we don't know which module it belongs to, since that is only
6232 * determined at assembly save time.
6234 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6235 name = mono_string_to_utf8 (ab->name);
6236 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6237 if (!mono_error_ok (&error)) {
6239 mono_error_raise_exception (&error);
6241 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6243 moduleb->module.image = &image->image;
6244 moduleb->dynamic_image = image;
6245 register_module (mono_object_domain (moduleb), moduleb, image);
6247 /* register the module with the assembly */
6248 ass = ab->dynamic_assembly->assembly.image;
6249 module_count = ass->module_count;
6250 new_modules = g_new0 (MonoImage *, module_count + 1);
6253 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6254 new_modules [module_count] = &image->image;
6255 mono_image_addref (&image->image);
6257 g_free (ass->modules);
6258 ass->modules = new_modules;
6259 ass->module_count ++;
6264 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6266 MonoDynamicImage *image = moduleb->dynamic_image;
6268 g_assert (type->type);
6269 image->wrappers_type = mono_class_from_mono_type (type->type);
6275 * mono_assembly_get_object:
6276 * @domain: an app domain
6277 * @assembly: an assembly
6279 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6281 MonoReflectionAssembly*
6282 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6284 static MonoClass *assembly_type;
6285 MonoReflectionAssembly *res;
6287 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6288 if (!assembly_type) {
6289 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6291 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6293 assembly_type = class;
6295 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6296 res->assembly = assembly;
6298 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6303 MonoReflectionModule*
6304 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6306 static MonoClass *module_type;
6307 MonoReflectionModule *res;
6310 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6312 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6314 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6316 module_type = class;
6318 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6321 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6323 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6324 basename = g_path_get_basename (image->name);
6325 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6326 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6330 if (image->assembly->image == image) {
6331 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6335 if (image->assembly->image->modules) {
6336 for (i = 0; i < image->assembly->image->module_count; i++) {
6337 if (image->assembly->image->modules [i] == image)
6338 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6340 g_assert (res->token);
6344 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6347 MonoReflectionModule*
6348 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6350 static MonoClass *module_type;
6351 MonoReflectionModule *res;
6352 MonoTableInfo *table;
6353 guint32 cols [MONO_FILE_SIZE];
6355 guint32 i, name_idx;
6359 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6361 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6363 module_type = class;
6365 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6367 table = &image->tables [MONO_TABLE_FILE];
6368 g_assert (table_index < table->rows);
6369 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6372 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6373 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6375 /* Check whenever the row has a corresponding row in the moduleref table */
6376 table = &image->tables [MONO_TABLE_MODULEREF];
6377 for (i = 0; i < table->rows; ++i) {
6378 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6379 val = mono_metadata_string_heap (image, name_idx);
6380 if (strcmp (val, name) == 0)
6381 res->image = image->modules [i];
6384 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6385 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6386 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6387 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6388 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6394 verify_safe_for_managed_space (MonoType *type)
6396 switch (type->type) {
6398 case MONO_TYPE_ARRAY:
6399 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6401 return verify_safe_for_managed_space (type->data.type);
6402 case MONO_TYPE_SZARRAY:
6403 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6404 case MONO_TYPE_GENERICINST: {
6405 MonoGenericInst *inst = type->data.generic_class->inst;
6409 for (i = 0; i < inst->type_argc; ++i)
6410 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6416 case MONO_TYPE_MVAR:
6424 mono_type_normalize (MonoType *type)
6427 MonoGenericClass *gclass;
6428 MonoGenericInst *ginst;
6430 MonoGenericContainer *gcontainer;
6431 MonoType **argv = NULL;
6432 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6434 if (type->type != MONO_TYPE_GENERICINST)
6437 gclass = type->data.generic_class;
6438 ginst = gclass->context.class_inst;
6439 if (!ginst->is_open)
6442 gtd = gclass->container_class;
6443 gcontainer = gtd->generic_container;
6444 argv = g_newa (MonoType*, ginst->type_argc);
6446 for (i = 0; i < ginst->type_argc; ++i) {
6447 MonoType *t = ginst->type_argv [i], *norm;
6448 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6449 is_denorm_gtd = FALSE;
6450 norm = mono_type_normalize (t);
6453 requires_rebind = TRUE;
6457 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6459 if (requires_rebind) {
6460 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6461 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6467 * mono_type_get_object:
6468 * @domain: an app domain
6471 * Return an System.MonoType object representing the type @type.
6474 mono_type_get_object (MonoDomain *domain, MonoType *type)
6476 MonoType *norm_type;
6477 MonoReflectionType *res;
6478 MonoClass *klass = mono_class_from_mono_type (type);
6480 /*we must avoid using @type as it might have come
6481 * from a mono_metadata_type_dup and the caller
6482 * expects that is can be freed.
6483 * Using the right type from
6485 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6487 /* void is very common */
6488 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6489 return (MonoReflectionType*)domain->typeof_void;
6492 * If the vtable of the given class was already created, we can use
6493 * the MonoType from there and avoid all locking and hash table lookups.
6495 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6496 * that the resulting object is different.
6498 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6499 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6500 if (vtable && vtable->type)
6501 return vtable->type;
6504 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6505 mono_domain_lock (domain);
6506 if (!domain->type_hash)
6507 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6508 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6509 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6510 mono_domain_unlock (domain);
6511 mono_loader_unlock ();
6515 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6516 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6517 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6518 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6519 * artifact of how generics are encoded and should be transparent to managed code so we
6520 * need to weed out this diference when retrieving managed System.Type objects.
6522 norm_type = mono_type_normalize (type);
6523 if (norm_type != type) {
6524 res = mono_type_get_object (domain, norm_type);
6525 mono_g_hash_table_insert (domain->type_hash, type, res);
6526 mono_domain_unlock (domain);
6527 mono_loader_unlock ();
6531 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6532 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6535 if (!verify_safe_for_managed_space (type)) {
6536 mono_domain_unlock (domain);
6537 mono_loader_unlock ();
6538 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6541 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6542 gboolean is_type_done = TRUE;
6543 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6544 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6545 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6547 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6548 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6550 if (gparam->owner && gparam->owner->is_method) {
6551 MonoMethod *method = gparam->owner->owner.method;
6552 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6553 is_type_done = FALSE;
6554 } else if (gparam->owner && !gparam->owner->is_method) {
6555 MonoClass *klass = gparam->owner->owner.klass;
6556 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6557 is_type_done = FALSE;
6561 /* g_assert_not_reached (); */
6562 /* should this be considered an error condition? */
6563 if (is_type_done && !type->byref) {
6564 mono_domain_unlock (domain);
6565 mono_loader_unlock ();
6566 return mono_class_get_ref_info (klass);
6569 /* This is stored in vtables/JITted code so it has to be pinned */
6570 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6572 mono_g_hash_table_insert (domain->type_hash, type, res);
6574 if (type->type == MONO_TYPE_VOID)
6575 domain->typeof_void = (MonoObject*)res;
6577 mono_domain_unlock (domain);
6578 mono_loader_unlock ();
6583 * mono_method_get_object:
6584 * @domain: an app domain
6586 * @refclass: the reflected type (can be NULL)
6588 * Return an System.Reflection.MonoMethod object representing the method @method.
6590 MonoReflectionMethod*
6591 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6594 * We use the same C representation for methods and constructors, but the type
6595 * name in C# is different.
6597 static MonoClass *System_Reflection_MonoMethod = NULL;
6598 static MonoClass *System_Reflection_MonoCMethod = NULL;
6599 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6600 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6602 MonoReflectionMethod *ret;
6604 if (method->is_inflated) {
6605 MonoReflectionGenericMethod *gret;
6607 refclass = method->klass;
6608 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6609 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6610 if (!System_Reflection_MonoGenericCMethod)
6611 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6612 klass = System_Reflection_MonoGenericCMethod;
6614 if (!System_Reflection_MonoGenericMethod)
6615 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6616 klass = System_Reflection_MonoGenericMethod;
6618 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6619 gret->method.method = method;
6620 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6621 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6622 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6626 refclass = method->klass;
6628 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6629 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6630 if (!System_Reflection_MonoCMethod)
6631 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6632 klass = System_Reflection_MonoCMethod;
6635 if (!System_Reflection_MonoMethod)
6636 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6637 klass = System_Reflection_MonoMethod;
6639 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6640 ret->method = method;
6641 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6642 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6646 * mono_method_clear_object:
6648 * Clear the cached reflection objects for the dynamic method METHOD.
6651 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6654 g_assert (method_is_dynamic (method));
6656 klass = method->klass;
6658 clear_cached_object (domain, method, klass);
6659 klass = klass->parent;
6661 /* Added by mono_param_get_objects () */
6662 clear_cached_object (domain, &(method->signature), NULL);
6663 klass = method->klass;
6665 clear_cached_object (domain, &(method->signature), klass);
6666 klass = klass->parent;
6671 * mono_field_get_object:
6672 * @domain: an app domain
6676 * Return an System.Reflection.MonoField object representing the field @field
6679 MonoReflectionField*
6680 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6682 MonoReflectionField *res;
6683 static MonoClass *monofield_klass;
6685 CHECK_OBJECT (MonoReflectionField *, field, klass);
6686 if (!monofield_klass)
6687 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6688 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6691 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6693 if (is_field_on_inst (field)) {
6694 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6695 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6698 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6699 res->attrs = mono_field_get_flags (field);
6701 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6705 * mono_property_get_object:
6706 * @domain: an app domain
6708 * @property: a property
6710 * Return an System.Reflection.MonoProperty object representing the property @property
6713 MonoReflectionProperty*
6714 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6716 MonoReflectionProperty *res;
6717 static MonoClass *monoproperty_klass;
6719 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6720 if (!monoproperty_klass)
6721 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6722 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6724 res->property = property;
6725 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6729 * mono_event_get_object:
6730 * @domain: an app domain
6734 * Return an System.Reflection.MonoEvent object representing the event @event
6737 MonoReflectionEvent*
6738 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6740 MonoReflectionEvent *res;
6741 MonoReflectionMonoEvent *mono_event;
6742 static MonoClass *monoevent_klass;
6744 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6745 if (!monoevent_klass)
6746 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6747 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6748 mono_event->klass = klass;
6749 mono_event->event = event;
6750 res = (MonoReflectionEvent*)mono_event;
6751 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6755 * mono_get_reflection_missing_object:
6756 * @domain: Domain where the object lives
6758 * Returns the System.Reflection.Missing.Value singleton object
6759 * (of type System.Reflection.Missing).
6761 * Used as the value for ParameterInfo.DefaultValue when Optional
6765 mono_get_reflection_missing_object (MonoDomain *domain)
6768 static MonoClassField *missing_value_field = NULL;
6770 if (!missing_value_field) {
6771 MonoClass *missing_klass;
6772 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6773 mono_class_init (missing_klass);
6774 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6775 g_assert (missing_value_field);
6777 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6783 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6786 *dbnull = mono_get_dbnull_object (domain);
6791 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6793 if (!*reflection_missing)
6794 *reflection_missing = mono_get_reflection_missing_object (domain);
6795 return *reflection_missing;
6799 * mono_param_get_objects:
6800 * @domain: an app domain
6803 * Return an System.Reflection.ParameterInfo array object representing the parameters
6804 * in the method @method.
6807 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6809 static MonoClass *System_Reflection_ParameterInfo;
6810 static MonoClass *System_Reflection_ParameterInfo_array;
6812 MonoArray *res = NULL;
6813 MonoReflectionMethod *member = NULL;
6814 MonoReflectionParameter *param = NULL;
6815 char **names, **blobs = NULL;
6816 guint32 *types = NULL;
6817 MonoType *type = NULL;
6818 MonoObject *dbnull = NULL;
6819 MonoObject *missing = NULL;
6820 MonoMarshalSpec **mspecs;
6821 MonoMethodSignature *sig;
6822 MonoVTable *pinfo_vtable;
6825 if (!System_Reflection_ParameterInfo_array) {
6828 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6830 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6832 mono_memory_barrier ();
6833 System_Reflection_ParameterInfo = klass;
6836 klass = mono_array_class_get (klass, 1);
6837 mono_memory_barrier ();
6838 System_Reflection_ParameterInfo_array = klass;
6841 sig = mono_method_signature_checked (method, &error);
6842 if (!mono_error_ok (&error))
6843 mono_error_raise_exception (&error);
6845 if (!sig->param_count)
6846 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6848 /* Note: the cache is based on the address of the signature into the method
6849 * since we already cache MethodInfos with the method as keys.
6851 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6853 member = mono_method_get_object (domain, method, refclass);
6854 names = g_new (char *, sig->param_count);
6855 mono_method_get_param_names (method, (const char **) names);
6857 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6858 mono_method_get_marshal_info (method, mspecs);
6860 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6861 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6862 for (i = 0; i < sig->param_count; ++i) {
6863 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6864 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6865 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6866 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6867 param->PositionImpl = i;
6868 param->AttrsImpl = sig->params [i]->attrs;
6870 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6871 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6872 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6874 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6878 blobs = g_new0 (char *, sig->param_count);
6879 types = g_new0 (guint32, sig->param_count);
6880 get_default_param_value_blobs (method, blobs, types);
6883 /* Build MonoType for the type from the Constant Table */
6885 type = g_new0 (MonoType, 1);
6886 type->type = types [i];
6887 type->data.klass = NULL;
6888 if (types [i] == MONO_TYPE_CLASS)
6889 type->data.klass = mono_defaults.object_class;
6890 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6891 /* For enums, types [i] contains the base type */
6893 type->type = MONO_TYPE_VALUETYPE;
6894 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6896 type->data.klass = mono_class_from_mono_type (type);
6898 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6900 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6901 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6902 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6903 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6905 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6911 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6913 mono_array_setref (res, i, param);
6920 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6922 mono_metadata_free_marshal_spec (mspecs [i]);
6925 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6929 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6931 return mono_param_get_objects_internal (domain, method, NULL);
6935 * mono_method_body_get_object:
6936 * @domain: an app domain
6939 * Return an System.Reflection.MethodBody object representing the method @method.
6941 MonoReflectionMethodBody*
6942 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6944 static MonoClass *System_Reflection_MethodBody = NULL;
6945 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6946 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6947 MonoReflectionMethodBody *ret;
6948 MonoMethodHeader *header;
6950 guint32 method_rva, local_var_sig_token;
6952 unsigned char format, flags;
6955 /* for compatibility with .net */
6956 if (method_is_dynamic (method))
6957 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6959 if (!System_Reflection_MethodBody)
6960 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6961 if (!System_Reflection_LocalVariableInfo)
6962 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6963 if (!System_Reflection_ExceptionHandlingClause)
6964 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6966 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6968 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6969 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6970 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6971 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6974 image = method->klass->image;
6975 header = mono_method_get_header (method);
6977 if (!image_is_dynamic (image)) {
6978 /* Obtain local vars signature token */
6979 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6980 ptr = mono_image_rva_map (image, method_rva);
6981 flags = *(const unsigned char *) ptr;
6982 format = flags & METHOD_HEADER_FORMAT_MASK;
6984 case METHOD_HEADER_TINY_FORMAT:
6985 local_var_sig_token = 0;
6987 case METHOD_HEADER_FAT_FORMAT:
6991 local_var_sig_token = read32 (ptr);
6994 g_assert_not_reached ();
6997 local_var_sig_token = 0; //FIXME
6999 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7001 ret->init_locals = header->init_locals;
7002 ret->max_stack = header->max_stack;
7003 ret->local_var_sig_token = local_var_sig_token;
7004 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7005 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7008 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7009 for (i = 0; i < header->num_locals; ++i) {
7010 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7011 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7012 info->is_pinned = header->locals [i]->pinned;
7013 info->local_index = i;
7014 mono_array_setref (ret->locals, i, info);
7018 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7019 for (i = 0; i < header->num_clauses; ++i) {
7020 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7021 MonoExceptionClause *clause = &header->clauses [i];
7023 info->flags = clause->flags;
7024 info->try_offset = clause->try_offset;
7025 info->try_length = clause->try_len;
7026 info->handler_offset = clause->handler_offset;
7027 info->handler_length = clause->handler_len;
7028 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7029 info->filter_offset = clause->data.filter_offset;
7030 else if (clause->data.catch_class)
7031 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7033 mono_array_setref (ret->clauses, i, info);
7036 mono_metadata_free_mh (header);
7037 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7042 * mono_get_dbnull_object:
7043 * @domain: Domain where the object lives
7045 * Returns the System.DBNull.Value singleton object
7047 * Used as the value for ParameterInfo.DefaultValue
7050 mono_get_dbnull_object (MonoDomain *domain)
7053 static MonoClassField *dbnull_value_field = NULL;
7055 if (!dbnull_value_field) {
7056 MonoClass *dbnull_klass;
7057 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7058 mono_class_init (dbnull_klass);
7059 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7060 g_assert (dbnull_value_field);
7062 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7068 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7070 guint32 param_index, i, lastp, crow = 0;
7071 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7074 MonoClass *klass = method->klass;
7075 MonoImage *image = klass->image;
7076 MonoMethodSignature *methodsig = mono_method_signature (method);
7078 MonoTableInfo *constt;
7079 MonoTableInfo *methodt;
7080 MonoTableInfo *paramt;
7082 if (!methodsig->param_count)
7085 mono_class_init (klass);
7087 if (image_is_dynamic (klass->image)) {
7088 MonoReflectionMethodAux *aux;
7089 if (method->is_inflated)
7090 method = ((MonoMethodInflated*)method)->declaring;
7091 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7092 if (aux && aux->param_defaults) {
7093 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7094 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7099 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7100 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7101 constt = &image->tables [MONO_TABLE_CONSTANT];
7103 idx = mono_method_get_index (method) - 1;
7104 g_assert (idx != -1);
7106 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7107 if (idx + 1 < methodt->rows)
7108 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7110 lastp = paramt->rows + 1;
7112 for (i = param_index; i < lastp; ++i) {
7115 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7116 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7118 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7121 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7126 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7127 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7128 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7135 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7140 MonoType *basetype = type;
7145 klass = mono_class_from_mono_type (type);
7146 if (klass->valuetype) {
7147 object = mono_object_new (domain, klass);
7148 retval = ((gchar *) object + sizeof (MonoObject));
7149 if (klass->enumtype)
7150 basetype = mono_class_enum_basetype (klass);
7155 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7162 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7165 gboolean quoted = FALSE;
7167 memset (assembly, 0, sizeof (MonoAssemblyName));
7168 assembly->culture = "";
7169 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7176 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7187 /* Remove trailing whitespace */
7189 while (*s && g_ascii_isspace (*s))
7192 while (g_ascii_isspace (*p))
7195 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7197 assembly->major = strtoul (p, &s, 10);
7198 if (s == p || *s != '.')
7201 assembly->minor = strtoul (p, &s, 10);
7202 if (s == p || *s != '.')
7205 assembly->build = strtoul (p, &s, 10);
7206 if (s == p || *s != '.')
7209 assembly->revision = strtoul (p, &s, 10);
7213 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7215 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7216 assembly->culture = "";
7219 assembly->culture = p;
7220 while (*p && *p != ',') {
7224 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7226 if (strncmp (p, "null", 4) == 0) {
7231 while (*p && *p != ',') {
7234 len = (p - start + 1);
7235 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7236 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7237 g_strlcpy ((char*)assembly->public_key_token, start, len);
7240 while (*p && *p != ',')
7244 while (g_ascii_isspace (*p) || *p == ',') {
7258 * mono_reflection_parse_type:
7261 * Parse a type name as accepted by the GetType () method and output the info
7262 * extracted in the info structure.
7263 * the name param will be mangled, so, make a copy before passing it to this function.
7264 * The fields in info will be valid until the memory pointed to by name is valid.
7266 * See also mono_type_get_name () below.
7268 * Returns: 0 on parse error.
7271 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7272 MonoTypeNameParse *info)
7274 char *start, *p, *w, *last_point, *startn;
7275 int in_modifiers = 0;
7276 int isbyref = 0, rank = 0;
7278 start = p = w = name;
7280 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7281 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7282 info->name = info->name_space = NULL;
7283 info->nested = NULL;
7284 info->modifiers = NULL;
7285 info->type_arguments = NULL;
7287 /* last_point separates the namespace from the name */
7290 while (*p == ' ') p++, start++, w++, name++;
7295 *p = 0; /* NULL terminate the name */
7297 info->nested = g_list_append (info->nested, startn);
7298 /* we have parsed the nesting namespace + name */
7302 info->name_space = start;
7304 info->name = last_point + 1;
7306 info->name_space = (char *)"";
7334 info->name_space = start;
7336 info->name = last_point + 1;
7338 info->name_space = (char *)"";
7345 if (isbyref) /* only one level allowed by the spec */
7348 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7352 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7356 //Decide if it's an array of a generic argument list
7361 if (*p == ',' || *p == '*' || *p == ']') { //array
7368 else if (*p == '*') /* '*' means unknown lower bound */
7369 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7376 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7378 if (rank) /* generic args after array spec*/ //XXX test
7380 info->type_arguments = g_ptr_array_new ();
7382 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7383 gboolean fqname = FALSE;
7385 g_ptr_array_add (info->type_arguments, subinfo);
7387 while (*p == ' ') p++;
7393 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7396 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7397 if (fqname && (*p != ']')) {
7405 while (*p && (*p != ']'))
7413 if (g_ascii_isspace (*aname)) {
7420 !assembly_name_to_aname (&subinfo->assembly, aname))
7422 } else if (fqname && (*p == ']')) {
7444 if (g_ascii_isspace (*p)) {
7451 return 0; /* missing assembly name */
7452 if (!assembly_name_to_aname (&info->assembly, p))
7458 if (info->assembly.name)
7461 // *w = 0; /* terminate class name */
7463 if (!info->name || !*info->name)
7467 /* add other consistency checks */
7472 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7474 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7478 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7480 gboolean type_resolve = FALSE;
7482 MonoImage *rootimage = image;
7484 if (info->assembly.name) {
7485 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7486 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7488 * This could happen in the AOT compiler case when the search hook is not
7491 assembly = image->assembly;
7493 /* then we must load the assembly ourselve - see #60439 */
7494 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7498 image = assembly->image;
7499 } else if (!image) {
7500 image = mono_defaults.corlib;
7503 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7504 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7505 image = mono_defaults.corlib;
7506 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7513 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7518 gboolean bounded = FALSE;
7521 image = mono_defaults.corlib;
7524 rootimage = mono_defaults.corlib;
7528 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7529 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7531 klass = mono_class_from_name (image, info->name_space, info->name);
7535 for (mod = info->nested; mod; mod = mod->next) {
7536 gpointer iter = NULL;
7540 mono_class_init (parent);
7542 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7544 char *nested_name, *nested_nspace;
7545 gboolean match = TRUE;
7547 lastp = strrchr (mod->data, '.');
7549 /* Nested classes can have namespaces */
7552 nested_name = g_strdup (lastp + 1);
7553 nspace_len = lastp - (char*)mod->data;
7554 nested_nspace = g_malloc (nspace_len + 1);
7555 memcpy (nested_nspace, mod->data, nspace_len);
7556 nested_nspace [nspace_len] = '\0';
7559 nested_name = mod->data;
7560 nested_nspace = NULL;
7563 if (nested_nspace) {
7565 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7568 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7574 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7577 if (strcmp (klass->name, nested_name) != 0)
7582 g_free (nested_name);
7583 g_free (nested_nspace);
7595 if (info->type_arguments) {
7596 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7597 MonoReflectionType *the_type;
7601 for (i = 0; i < info->type_arguments->len; i++) {
7602 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7604 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7605 if (!type_args [i]) {
7611 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7613 instance = mono_reflection_bind_generic_parameters (
7614 the_type, info->type_arguments->len, type_args);
7620 klass = mono_class_from_mono_type (instance);
7623 for (mod = info->modifiers; mod; mod = mod->next) {
7624 modval = GPOINTER_TO_UINT (mod->data);
7625 if (!modval) { /* byref: must be last modifier */
7626 return &klass->this_arg;
7627 } else if (modval == -1) {
7628 klass = mono_ptr_class_get (&klass->byval_arg);
7629 } else if (modval == -2) {
7631 } else { /* array rank */
7632 klass = mono_bounded_array_class_get (klass, modval, bounded);
7636 return &klass->byval_arg;
7640 * mono_reflection_get_type:
7641 * @image: a metadata context
7642 * @info: type description structure
7643 * @ignorecase: flag for case-insensitive string compares
7644 * @type_resolve: whenever type resolve was already tried
7646 * Build a MonoType from the type description in @info.
7651 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7652 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7656 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7658 MonoReflectionAssemblyBuilder *abuilder;
7662 g_assert (assembly_is_dynamic (assembly));
7663 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7665 /* Enumerate all modules */
7668 if (abuilder->modules) {
7669 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7670 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7671 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7677 if (!type && abuilder->loaded_modules) {
7678 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7679 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7680 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7690 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7693 MonoReflectionAssembly *assembly;
7697 if (image && image_is_dynamic (image))
7698 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7700 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7703 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7710 *type_resolve = TRUE;
7713 /* Reconstruct the type name */
7714 fullName = g_string_new ("");
7715 if (info->name_space && (info->name_space [0] != '\0'))
7716 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7718 g_string_printf (fullName, "%s", info->name);
7719 for (mod = info->nested; mod; mod = mod->next)
7720 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7722 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7724 if (assembly_is_dynamic (assembly->assembly))
7725 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7727 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7730 g_string_free (fullName, TRUE);
7735 mono_reflection_free_type_info (MonoTypeNameParse *info)
7737 g_list_free (info->modifiers);
7738 g_list_free (info->nested);
7740 if (info->type_arguments) {
7743 for (i = 0; i < info->type_arguments->len; i++) {
7744 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7746 mono_reflection_free_type_info (subinfo);
7747 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7751 g_ptr_array_free (info->type_arguments, TRUE);
7756 * mono_reflection_type_from_name:
7758 * @image: a metadata context (can be NULL).
7760 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7761 * it defaults to get the type from @image or, if @image is NULL or loading
7762 * from it fails, uses corlib.
7766 mono_reflection_type_from_name (char *name, MonoImage *image)
7768 MonoType *type = NULL;
7769 MonoTypeNameParse info;
7772 /* Make a copy since parse_type modifies its argument */
7773 tmp = g_strdup (name);
7775 /*g_print ("requested type %s\n", str);*/
7776 if (mono_reflection_parse_type (tmp, &info)) {
7777 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7781 mono_reflection_free_type_info (&info);
7786 * mono_reflection_get_token:
7788 * Return the metadata token of OBJ which should be an object
7789 * representing a metadata element.
7792 mono_reflection_get_token (MonoObject *obj)
7797 klass = obj->vtable->klass;
7799 if (strcmp (klass->name, "MethodBuilder") == 0) {
7800 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7802 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7803 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7804 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7806 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7807 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7808 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7810 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7811 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7812 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7813 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7814 } else if (strcmp (klass->name, "MonoType") == 0) {
7815 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7816 MonoClass *mc = mono_class_from_mono_type (type);
7817 if (!mono_class_init (mc))
7818 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7820 token = mc->type_token;
7821 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7822 strcmp (klass->name, "MonoMethod") == 0 ||
7823 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7824 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7825 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7826 if (m->method->is_inflated) {
7827 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7828 return inflated->declaring->token;
7830 token = m->method->token;
7832 } else if (strcmp (klass->name, "MonoField") == 0) {
7833 MonoReflectionField *f = (MonoReflectionField*)obj;
7835 if (is_field_on_inst (f->field)) {
7836 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7838 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7839 int field_index = f->field - dgclass->fields;
7842 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7843 obj = dgclass->field_objects [field_index];
7844 return mono_reflection_get_token (obj);
7847 token = mono_class_get_field_token (f->field);
7848 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7849 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7851 token = mono_class_get_property_token (p->property);
7852 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7853 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7855 token = mono_class_get_event_token (p->event);
7856 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7857 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7858 MonoClass *member_class = mono_object_class (p->MemberImpl);
7859 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7861 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7862 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7863 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7866 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7867 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7869 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7870 MonoException *ex = mono_get_exception_not_implemented (msg);
7872 mono_raise_exception (ex);
7879 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7883 int slen = mono_metadata_decode_value (p, &p);
7885 mono_error_init (error);
7887 n = g_memdup (p, slen + 1);
7889 t = mono_reflection_type_from_name (n, image);
7891 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7892 /* We don't free n, it's consumed by mono_error */
7893 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7899 return mono_class_from_mono_type (t);
7903 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7905 int slen, type = t->type;
7906 MonoClass *tklass = t->data.klass;
7908 mono_error_init (error);
7914 case MONO_TYPE_BOOLEAN: {
7915 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7920 case MONO_TYPE_CHAR:
7922 case MONO_TYPE_I2: {
7923 guint16 *val = g_malloc (sizeof (guint16));
7928 #if SIZEOF_VOID_P == 4
7934 case MONO_TYPE_I4: {
7935 guint32 *val = g_malloc (sizeof (guint32));
7940 #if SIZEOF_VOID_P == 8
7941 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7945 case MONO_TYPE_I8: {
7946 guint64 *val = g_malloc (sizeof (guint64));
7951 case MONO_TYPE_R8: {
7952 double *val = g_malloc (sizeof (double));
7957 case MONO_TYPE_VALUETYPE:
7958 if (t->data.klass->enumtype) {
7959 type = mono_class_enum_basetype (t->data.klass)->type;
7962 MonoClass *k = t->data.klass;
7964 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7965 guint64 *val = g_malloc (sizeof (guint64));
7971 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7974 case MONO_TYPE_STRING:
7975 if (*p == (char)0xFF) {
7979 slen = mono_metadata_decode_value (p, &p);
7981 return mono_string_new_len (mono_domain_get (), p, slen);
7982 case MONO_TYPE_CLASS: {
7985 if (*p == (char)0xFF) {
7990 slen = mono_metadata_decode_value (p, &p);
7991 n = g_memdup (p, slen + 1);
7993 t = mono_reflection_type_from_name (n, image);
7995 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7996 /* We don't free n, it's consumed by mono_error */
7997 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8002 return mono_type_get_object (mono_domain_get (), t);
8004 case MONO_TYPE_OBJECT: {
8007 MonoClass *subc = NULL;
8012 } else if (subt == 0x0E) {
8013 type = MONO_TYPE_STRING;
8015 } else if (subt == 0x1D) {
8016 MonoType simple_type = {{0}};
8020 type = MONO_TYPE_SZARRAY;
8021 if (etype == 0x50) {
8022 tklass = mono_defaults.systemtype_class;
8023 } else if (etype == 0x55) {
8024 tklass = load_cattr_enum_type (image, p, &p, error);
8025 if (!mono_error_ok (error))
8029 /* See Partition II, Appendix B3 */
8030 etype = MONO_TYPE_OBJECT;
8031 simple_type.type = etype;
8032 tklass = mono_class_from_mono_type (&simple_type);
8035 } else if (subt == 0x55) {
8038 slen = mono_metadata_decode_value (p, &p);
8039 n = g_memdup (p, slen + 1);
8041 t = mono_reflection_type_from_name (n, image);
8043 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8044 /* We don't free n, it's consumed by mono_error */
8045 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8050 subc = mono_class_from_mono_type (t);
8051 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8052 MonoType simple_type = {{0}};
8053 simple_type.type = subt;
8054 subc = mono_class_from_mono_type (&simple_type);
8056 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8058 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8060 if (mono_error_ok (error)) {
8061 obj = mono_object_new (mono_domain_get (), subc);
8062 g_assert (!subc->has_references);
8063 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8069 case MONO_TYPE_SZARRAY: {
8071 guint32 i, alen, basetype;
8074 if (alen == 0xffffffff) {
8078 arr = mono_array_new (mono_domain_get(), tklass, alen);
8079 basetype = tklass->byval_arg.type;
8080 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8081 basetype = mono_class_enum_basetype (tklass)->type;
8086 case MONO_TYPE_BOOLEAN:
8087 for (i = 0; i < alen; i++) {
8088 MonoBoolean val = *p++;
8089 mono_array_set (arr, MonoBoolean, i, val);
8092 case MONO_TYPE_CHAR:
8095 for (i = 0; i < alen; i++) {
8096 guint16 val = read16 (p);
8097 mono_array_set (arr, guint16, i, val);
8104 for (i = 0; i < alen; i++) {
8105 guint32 val = read32 (p);
8106 mono_array_set (arr, guint32, i, val);
8111 for (i = 0; i < alen; i++) {
8114 mono_array_set (arr, double, i, val);
8120 for (i = 0; i < alen; i++) {
8121 guint64 val = read64 (p);
8122 mono_array_set (arr, guint64, i, val);
8126 case MONO_TYPE_CLASS:
8127 case MONO_TYPE_OBJECT:
8128 case MONO_TYPE_STRING:
8129 case MONO_TYPE_SZARRAY:
8130 for (i = 0; i < alen; i++) {
8131 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8132 if (!mono_error_ok (error))
8134 mono_array_setref (arr, i, item);
8138 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8144 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8150 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8152 static MonoClass *klass;
8153 static MonoMethod *ctor;
8155 void *params [2], *unboxed;
8158 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8160 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8162 params [0] = mono_type_get_object (mono_domain_get (), t);
8164 retval = mono_object_new (mono_domain_get (), klass);
8165 unboxed = mono_object_unbox (retval);
8166 mono_runtime_invoke (ctor, unboxed, params, NULL);
8172 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8174 static MonoClass *klass;
8175 static MonoMethod *ctor;
8177 void *unboxed, *params [2];
8180 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8182 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8185 params [1] = typedarg;
8186 retval = mono_object_new (mono_domain_get (), klass);
8187 unboxed = mono_object_unbox (retval);
8188 mono_runtime_invoke (ctor, unboxed, params, NULL);
8194 type_is_reference (MonoType *type)
8196 switch (type->type) {
8197 case MONO_TYPE_BOOLEAN:
8198 case MONO_TYPE_CHAR:
8211 case MONO_TYPE_VALUETYPE:
8219 free_param_data (MonoMethodSignature *sig, void **params) {
8221 for (i = 0; i < sig->param_count; ++i) {
8222 if (!type_is_reference (sig->params [i]))
8223 g_free (params [i]);
8228 * Find the field index in the metadata FieldDef table.
8231 find_field_index (MonoClass *klass, MonoClassField *field) {
8234 for (i = 0; i < klass->field.count; ++i) {
8235 if (field == &klass->fields [i])
8236 return klass->field.first + 1 + i;
8242 * Find the property index in the metadata Property table.
8245 find_property_index (MonoClass *klass, MonoProperty *property) {
8248 for (i = 0; i < klass->ext->property.count; ++i) {
8249 if (property == &klass->ext->properties [i])
8250 return klass->ext->property.first + 1 + i;
8256 * Find the event index in the metadata Event table.
8259 find_event_index (MonoClass *klass, MonoEvent *event) {
8262 for (i = 0; i < klass->ext->event.count; ++i) {
8263 if (event == &klass->ext->events [i])
8264 return klass->ext->event.first + 1 + i;
8270 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8272 const char *p = (const char*)data;
8274 guint32 i, j, num_named;
8276 void *params_buf [32];
8277 void **params = NULL;
8278 MonoMethodSignature *sig;
8279 MonoObject *exc = NULL;
8281 mono_error_init (error);
8283 mono_class_init (method->klass);
8285 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8286 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8291 attr = mono_object_new (mono_domain_get (), method->klass);
8292 mono_runtime_invoke (method, attr, NULL, NULL);
8296 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8299 /*g_print ("got attr %s\n", method->klass->name);*/
8301 sig = mono_method_signature (method);
8302 if (sig->param_count < 32) {
8303 params = params_buf;
8304 memset (params, 0, sizeof (void*) * sig->param_count);
8306 /* Allocate using GC so it gets GC tracking */
8307 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8312 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8313 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8314 if (!mono_error_ok (error))
8319 attr = mono_object_new (mono_domain_get (), method->klass);
8321 mono_runtime_invoke (method, attr, params, &exc);
8324 num_named = read16 (named);
8326 for (j = 0; j < num_named; j++) {
8328 char *name, named_type, data_type;
8329 named_type = *named++;
8330 data_type = *named++; /* type of data */
8331 if (data_type == MONO_TYPE_SZARRAY)
8332 data_type = *named++;
8333 if (data_type == MONO_TYPE_ENUM) {
8336 type_len = mono_metadata_decode_blob_size (named, &named);
8337 type_name = g_malloc (type_len + 1);
8338 memcpy (type_name, named, type_len);
8339 type_name [type_len] = 0;
8341 /* FIXME: lookup the type and check type consistency */
8344 name_len = mono_metadata_decode_blob_size (named, &named);
8345 name = g_malloc (name_len + 1);
8346 memcpy (name, named, name_len);
8347 name [name_len] = 0;
8349 if (named_type == 0x53) {
8350 MonoClassField *field;
8353 /* how this fail is a blackbox */
8354 field = mono_class_get_field_from_name (mono_object_class (attr), name);
8356 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8361 val = load_cattr_value (image, field->type, named, &named, error);
8362 if (!mono_error_ok (error)) {
8364 if (!type_is_reference (field->type))
8369 mono_field_set_value (attr, field, val);
8370 if (!type_is_reference (field->type))
8372 } else if (named_type == 0x54) {
8375 MonoType *prop_type;
8377 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8380 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8386 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8391 /* can we have more that 1 arg in a custom attr named property? */
8392 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8393 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8395 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8396 if (!mono_error_ok (error)) {
8398 if (!type_is_reference (prop_type))
8399 g_free (pparams [0]);
8404 mono_property_set_value (prop, attr, pparams, NULL);
8405 if (!type_is_reference (prop_type))
8406 g_free (pparams [0]);
8411 free_param_data (method->signature, params);
8412 if (params != params_buf)
8413 mono_gc_free_fixed (params);
8418 free_param_data (method->signature, params);
8419 if (params != params_buf)
8420 mono_gc_free_fixed (params);
8422 mono_raise_exception ((MonoException*)exc);
8427 * mono_reflection_create_custom_attr_data_args:
8429 * Create an array of typed and named arguments from the cattr blob given by DATA.
8430 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8431 * NAMED_ARG_INFO will contain information about the named arguments.
8434 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)
8436 MonoArray *typedargs, *namedargs;
8437 MonoClass *attrklass;
8439 const char *p = (const char*)data;
8441 guint32 i, j, num_named;
8442 CattrNamedArg *arginfo = NULL;
8446 *named_arg_info = NULL;
8448 mono_error_init (error);
8450 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8451 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8455 mono_class_init (method->klass);
8457 domain = mono_domain_get ();
8459 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8462 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8466 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8470 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8471 if (!mono_error_ok (error)) {
8472 if (!type_is_reference (mono_method_signature (method)->params [i]))
8477 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8478 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8479 mono_array_setref (typedargs, i, obj);
8481 if (!type_is_reference (mono_method_signature (method)->params [i]))
8486 num_named = read16 (named);
8487 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8489 attrklass = method->klass;
8491 arginfo = g_new0 (CattrNamedArg, num_named);
8492 *named_arg_info = arginfo;
8494 for (j = 0; j < num_named; j++) {
8496 char *name, named_type, data_type;
8497 named_type = *named++;
8498 data_type = *named++; /* type of data */
8499 if (data_type == MONO_TYPE_SZARRAY)
8500 data_type = *named++;
8501 if (data_type == MONO_TYPE_ENUM) {
8504 type_len = mono_metadata_decode_blob_size (named, &named);
8505 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8508 type_name = g_malloc (type_len + 1);
8509 memcpy (type_name, named, type_len);
8510 type_name [type_len] = 0;
8512 /* FIXME: lookup the type and check type consistency */
8515 name_len = mono_metadata_decode_blob_size (named, &named);
8516 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8518 name = g_malloc (name_len + 1);
8519 memcpy (name, named, name_len);
8520 name [name_len] = 0;
8522 if (named_type == 0x53) {
8524 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8532 arginfo [j].type = field->type;
8533 arginfo [j].field = field;
8535 val = load_cattr_value (image, field->type, named, &named, error);
8536 if (!mono_error_ok (error)) {
8537 if (!type_is_reference (field->type))
8543 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8544 mono_array_setref (namedargs, j, obj);
8545 if (!type_is_reference (field->type))
8547 } else if (named_type == 0x54) {
8549 MonoType *prop_type;
8550 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8553 if (!prop || !prop->set) {
8558 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8559 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8561 arginfo [j].type = prop_type;
8562 arginfo [j].prop = prop;
8564 val = load_cattr_value (image, prop_type, named, &named, error);
8565 if (!mono_error_ok (error)) {
8566 if (!type_is_reference (prop_type))
8572 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8573 mono_array_setref (namedargs, j, obj);
8574 if (!type_is_reference (prop_type))
8580 *typed_args = typedargs;
8581 *named_args = namedargs;
8584 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8586 *named_arg_info = NULL;
8590 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8593 MonoArray *typedargs, *namedargs;
8596 CattrNamedArg *arginfo = NULL;
8606 image = assembly->assembly->image;
8607 method = ref_method->method;
8608 domain = mono_object_domain (ref_method);
8610 if (!mono_class_init (method->klass))
8611 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8613 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8614 if (!mono_error_ok (&error))
8615 mono_error_raise_exception (&error);
8616 if (mono_loader_get_last_error ())
8617 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8619 if (!typedargs || !namedargs) {
8624 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8625 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8626 MonoObject *typedarg;
8628 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8629 mono_array_setref (typedargs, i, typedarg);
8632 for (i = 0; i < mono_array_length (namedargs); ++i) {
8633 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8634 MonoObject *typedarg, *namedarg, *minfo;
8636 if (arginfo [i].prop)
8637 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8639 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8641 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8642 namedarg = create_cattr_named_arg (minfo, typedarg);
8644 mono_array_setref (namedargs, i, namedarg);
8647 *ctor_args = typedargs;
8648 *named_args = namedargs;
8653 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8655 static MonoMethod *ctor;
8660 g_assert (image->assembly);
8663 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8665 domain = mono_domain_get ();
8666 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8667 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8668 params [1] = mono_assembly_get_object (domain, image->assembly);
8669 params [2] = (gpointer)&cattr->data;
8670 params [3] = &cattr->data_size;
8671 mono_runtime_invoke (ctor, attr, params, NULL);
8676 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8682 mono_error_init (error);
8685 for (i = 0; i < cinfo->num_attrs; ++i) {
8686 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8690 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8692 for (i = 0; i < cinfo->num_attrs; ++i) {
8693 if (!cinfo->attrs [i].ctor)
8694 /* The cattr type is not finished yet */
8695 /* We should include the type name but cinfo doesn't contain it */
8696 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8697 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8698 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8699 if (!mono_error_ok (error))
8701 mono_array_setref (result, n, attr);
8709 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8712 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8713 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8719 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8725 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8726 for (i = 0; i < cinfo->num_attrs; ++i) {
8727 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8728 mono_array_setref (result, i, attr);
8734 * mono_custom_attrs_from_index:
8736 * Returns: NULL if no attributes are found or if a loading error occurs.
8739 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8741 guint32 mtoken, i, len;
8742 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8744 MonoCustomAttrInfo *ainfo;
8745 GList *tmp, *list = NULL;
8747 MonoCustomAttrEntry* attr;
8749 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8751 i = mono_metadata_custom_attrs_from_index (image, idx);
8755 while (i < ca->rows) {
8756 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8758 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8761 len = g_list_length (list);
8764 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8765 ainfo->num_attrs = len;
8766 ainfo->image = image;
8767 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8768 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8769 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8770 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8771 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8772 mtoken |= MONO_TOKEN_METHOD_DEF;
8774 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8775 mtoken |= MONO_TOKEN_MEMBER_REF;
8778 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8781 attr = &ainfo->attrs [i - 1];
8782 attr->ctor = mono_get_method (image, mtoken, NULL);
8784 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8790 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8791 /*FIXME raising an exception here doesn't make any sense*/
8792 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8797 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8798 attr->data_size = mono_metadata_decode_value (data, &data);
8799 attr->data = (guchar*)data;
8807 mono_custom_attrs_from_method (MonoMethod *method)
8812 * An instantiated method has the same cattrs as the generic method definition.
8814 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8815 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8817 if (method->is_inflated)
8818 method = ((MonoMethodInflated *) method)->declaring;
8820 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8821 return lookup_custom_attr (method->klass->image, method);
8824 /* Synthetic methods */
8827 idx = mono_method_get_index (method);
8828 idx <<= MONO_CUSTOM_ATTR_BITS;
8829 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8830 return mono_custom_attrs_from_index (method->klass->image, idx);
8834 mono_custom_attrs_from_class (MonoClass *klass)
8838 if (klass->generic_class)
8839 klass = klass->generic_class->container_class;
8841 if (image_is_dynamic (klass->image))
8842 return lookup_custom_attr (klass->image, klass);
8844 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8845 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8846 idx <<= MONO_CUSTOM_ATTR_BITS;
8847 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8849 idx = mono_metadata_token_index (klass->type_token);
8850 idx <<= MONO_CUSTOM_ATTR_BITS;
8851 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8853 return mono_custom_attrs_from_index (klass->image, idx);
8857 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8861 if (image_is_dynamic (assembly->image))
8862 return lookup_custom_attr (assembly->image, assembly);
8863 idx = 1; /* there is only one assembly */
8864 idx <<= MONO_CUSTOM_ATTR_BITS;
8865 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8866 return mono_custom_attrs_from_index (assembly->image, idx);
8869 static MonoCustomAttrInfo*
8870 mono_custom_attrs_from_module (MonoImage *image)
8874 if (image_is_dynamic (image))
8875 return lookup_custom_attr (image, image);
8876 idx = 1; /* there is only one module */
8877 idx <<= MONO_CUSTOM_ATTR_BITS;
8878 idx |= MONO_CUSTOM_ATTR_MODULE;
8879 return mono_custom_attrs_from_index (image, idx);
8883 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8887 if (image_is_dynamic (klass->image)) {
8888 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8889 return lookup_custom_attr (klass->image, property);
8891 idx = find_property_index (klass, property);
8892 idx <<= MONO_CUSTOM_ATTR_BITS;
8893 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8894 return mono_custom_attrs_from_index (klass->image, idx);
8898 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8902 if (image_is_dynamic (klass->image)) {
8903 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8904 return lookup_custom_attr (klass->image, event);
8906 idx = find_event_index (klass, event);
8907 idx <<= MONO_CUSTOM_ATTR_BITS;
8908 idx |= MONO_CUSTOM_ATTR_EVENT;
8909 return mono_custom_attrs_from_index (klass->image, idx);
8913 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8916 if (image_is_dynamic (klass->image)) {
8917 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8918 return lookup_custom_attr (klass->image, field);
8920 idx = find_field_index (klass, field);
8921 idx <<= MONO_CUSTOM_ATTR_BITS;
8922 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8923 return mono_custom_attrs_from_index (klass->image, idx);
8927 * mono_custom_attrs_from_param:
8928 * @method: handle to the method that we want to retrieve custom parameter information from
8929 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8931 * The result must be released with mono_custom_attrs_free().
8933 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8936 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8939 guint32 i, idx, method_index;
8940 guint32 param_list, param_last, param_pos, found;
8942 MonoReflectionMethodAux *aux;
8945 * An instantiated method has the same cattrs as the generic method definition.
8947 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8948 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8950 if (method->is_inflated)
8951 method = ((MonoMethodInflated *) method)->declaring;
8953 if (image_is_dynamic (method->klass->image)) {
8954 MonoCustomAttrInfo *res, *ainfo;
8957 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8958 if (!aux || !aux->param_cattr)
8961 /* Need to copy since it will be freed later */
8962 ainfo = aux->param_cattr [param];
8965 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8966 res = g_malloc0 (size);
8967 memcpy (res, ainfo, size);
8971 image = method->klass->image;
8972 method_index = mono_method_get_index (method);
8975 ca = &image->tables [MONO_TABLE_METHOD];
8977 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8978 if (method_index == ca->rows) {
8979 ca = &image->tables [MONO_TABLE_PARAM];
8980 param_last = ca->rows + 1;
8982 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8983 ca = &image->tables [MONO_TABLE_PARAM];
8986 for (i = param_list; i < param_last; ++i) {
8987 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8988 if (param_pos == param) {
8996 idx <<= MONO_CUSTOM_ATTR_BITS;
8997 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8998 return mono_custom_attrs_from_index (image, idx);
9002 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9006 for (i = 0; i < ainfo->num_attrs; ++i) {
9007 klass = ainfo->attrs [i].ctor->klass;
9008 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9015 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9018 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9019 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9024 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9030 mono_error_init (error);
9033 for (i = 0; i < ainfo->num_attrs; ++i) {
9034 klass = ainfo->attrs [i].ctor->klass;
9035 if (mono_class_has_parent (klass, attr_klass)) {
9040 if (attr_index == -1)
9043 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9044 if (!mono_error_ok (error))
9046 return mono_array_get (attrs, MonoObject*, attr_index);
9050 * mono_reflection_get_custom_attrs_info:
9051 * @obj: a reflection object handle
9053 * Return the custom attribute info for attributes defined for the
9054 * reflection handle @obj. The objects.
9056 * FIXME this function leaks like a sieve for SRE objects.
9059 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9062 MonoCustomAttrInfo *cinfo = NULL;
9064 klass = obj->vtable->klass;
9065 if (klass == mono_defaults.monotype_class) {
9066 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9067 klass = mono_class_from_mono_type (type);
9068 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9069 cinfo = mono_custom_attrs_from_class (klass);
9070 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9071 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9072 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9073 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9074 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9075 cinfo = mono_custom_attrs_from_module (module->image);
9076 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9077 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9078 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9079 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9080 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9081 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9082 } else if (strcmp ("MonoField", klass->name) == 0) {
9083 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9084 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9085 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9086 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9087 cinfo = mono_custom_attrs_from_method (rmethod->method);
9088 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9089 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9090 cinfo = mono_custom_attrs_from_method (rmethod->method);
9091 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9092 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9093 MonoClass *member_class = mono_object_class (param->MemberImpl);
9094 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9095 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9096 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9097 } else if (is_sr_mono_property (member_class)) {
9098 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9100 if (!(method = prop->property->get))
9101 method = prop->property->set;
9104 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9106 #ifndef DISABLE_REFLECTION_EMIT
9107 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9108 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9109 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9110 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9111 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9112 MonoMethod *method = NULL;
9113 if (is_sre_ctor_builder (mono_object_class (c->cb)))
9114 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9115 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9116 method = ((MonoReflectionMethod *)c->cb)->method;
9118 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));
9120 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9124 char *type_name = mono_type_get_full_name (member_class);
9125 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9126 MonoException *ex = mono_get_exception_not_supported (msg);
9129 mono_raise_exception (ex);
9131 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9132 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9133 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9134 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9135 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9136 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9137 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9138 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9139 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9140 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9141 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9142 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9143 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9144 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9145 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9146 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9147 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9148 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9149 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9150 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9151 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9152 } else { /* handle other types here... */
9153 g_error ("get custom attrs not yet supported for %s", klass->name);
9160 * mono_reflection_get_custom_attrs_by_type:
9161 * @obj: a reflection object handle
9163 * Return an array with all the custom attributes defined of the
9164 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
9165 * of that type are returned. The objects are fully build. Return NULL if a loading error
9169 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9172 MonoCustomAttrInfo *cinfo;
9174 mono_error_init (error);
9176 cinfo = mono_reflection_get_custom_attrs_info (obj);
9178 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9180 mono_custom_attrs_free (cinfo);
9182 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9183 if (mono_loader_get_last_error ())
9185 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9192 * mono_reflection_get_custom_attrs:
9193 * @obj: a reflection object handle
9195 * Return an array with all the custom attributes defined of the
9196 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9200 mono_reflection_get_custom_attrs (MonoObject *obj)
9204 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9208 * mono_reflection_get_custom_attrs_data:
9209 * @obj: a reflection obj handle
9211 * Returns an array of System.Reflection.CustomAttributeData,
9212 * which include information about attributes reflected on
9213 * types loaded using the Reflection Only methods
9216 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9219 MonoCustomAttrInfo *cinfo;
9221 cinfo = mono_reflection_get_custom_attrs_info (obj);
9223 result = mono_custom_attrs_data_construct (cinfo);
9225 mono_custom_attrs_free (cinfo);
9227 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9232 static MonoReflectionType*
9233 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9235 static MonoMethod *method_get_underlying_system_type = NULL;
9236 MonoMethod *usertype_method;
9238 if (!method_get_underlying_system_type)
9239 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9240 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9241 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9246 is_corlib_type (MonoClass *class)
9248 return class->image == mono_defaults.corlib;
9251 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9252 static MonoClass *cached_class; \
9254 return cached_class == _class; \
9255 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9256 cached_class = _class; \
9263 #ifndef DISABLE_REFLECTION_EMIT
9265 is_sre_array (MonoClass *class)
9267 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9271 is_sre_byref (MonoClass *class)
9273 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9277 is_sre_pointer (MonoClass *class)
9279 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9283 is_sre_generic_instance (MonoClass *class)
9285 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9289 is_sre_type_builder (MonoClass *class)
9291 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9295 is_sre_method_builder (MonoClass *class)
9297 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9301 is_sre_ctor_builder (MonoClass *class)
9303 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9307 is_sre_field_builder (MonoClass *class)
9309 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9313 is_sre_method_on_tb_inst (MonoClass *class)
9315 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9319 is_sre_ctor_on_tb_inst (MonoClass *class)
9321 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9325 mono_reflection_type_get_handle (MonoReflectionType* ref)
9333 if (is_usertype (ref)) {
9334 ref = mono_reflection_type_get_underlying_system_type (ref);
9335 if (ref == NULL || is_usertype (ref))
9341 class = mono_object_class (ref);
9343 if (is_sre_array (class)) {
9345 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9346 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9348 if (sre_array->rank == 0) //single dimentional array
9349 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9351 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9352 sre_array->type.type = res;
9354 } else if (is_sre_byref (class)) {
9356 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9357 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9359 res = &mono_class_from_mono_type (base)->this_arg;
9360 sre_byref->type.type = res;
9362 } else if (is_sre_pointer (class)) {
9364 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9365 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9367 res = &mono_ptr_class_get (base)->byval_arg;
9368 sre_pointer->type.type = res;
9370 } else if (is_sre_generic_instance (class)) {
9371 MonoType *res, **types;
9372 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9375 count = mono_array_length (gclass->type_arguments);
9376 types = g_new0 (MonoType*, count);
9377 for (i = 0; i < count; ++i) {
9378 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9379 types [i] = mono_reflection_type_get_handle (t);
9386 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9389 gclass->type.type = res;
9393 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9400 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9402 mono_reflection_type_get_handle (type);
9406 mono_reflection_register_with_runtime (MonoReflectionType *type)
9408 MonoType *res = mono_reflection_type_get_handle (type);
9409 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9413 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9415 class = mono_class_from_mono_type (res);
9417 mono_loader_lock (); /*same locking as mono_type_get_object*/
9418 mono_domain_lock (domain);
9420 if (!image_is_dynamic (class->image)) {
9421 mono_class_setup_supertypes (class);
9423 if (!domain->type_hash)
9424 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9425 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9426 mono_g_hash_table_insert (domain->type_hash, res, type);
9428 mono_domain_unlock (domain);
9429 mono_loader_unlock ();
9433 * LOCKING: Assumes the loader lock is held.
9435 static MonoMethodSignature*
9436 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9437 MonoMethodSignature *sig;
9440 count = parameters? mono_array_length (parameters): 0;
9442 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9443 sig->param_count = count;
9444 sig->sentinelpos = -1; /* FIXME */
9445 for (i = 0; i < count; ++i)
9446 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9451 * LOCKING: Assumes the loader lock is held.
9453 static MonoMethodSignature*
9454 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9455 MonoMethodSignature *sig;
9457 sig = parameters_to_signature (image, ctor->parameters);
9458 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9459 sig->ret = &mono_defaults.void_class->byval_arg;
9464 * LOCKING: Assumes the loader lock is held.
9466 static MonoMethodSignature*
9467 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9468 MonoMethodSignature *sig;
9470 sig = parameters_to_signature (image, method->parameters);
9471 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9472 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9473 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9477 static MonoMethodSignature*
9478 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9479 MonoMethodSignature *sig;
9481 sig = parameters_to_signature (NULL, method->parameters);
9482 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9483 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9484 sig->generic_param_count = 0;
9489 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9491 MonoClass *klass = mono_object_class (prop);
9492 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9493 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9494 *name = mono_string_to_utf8 (pb->name);
9495 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9497 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9498 *name = g_strdup (p->property->name);
9499 if (p->property->get)
9500 *type = mono_method_signature (p->property->get)->ret;
9502 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9507 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9509 MonoClass *klass = mono_object_class (field);
9510 if (strcmp (klass->name, "FieldBuilder") == 0) {
9511 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9512 *name = mono_string_to_utf8 (fb->name);
9513 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9515 MonoReflectionField *f = (MonoReflectionField *)field;
9516 *name = g_strdup (mono_field_get_name (f->field));
9517 *type = f->field->type;
9521 #else /* DISABLE_REFLECTION_EMIT */
9524 mono_reflection_register_with_runtime (MonoReflectionType *type)
9530 is_sre_type_builder (MonoClass *class)
9536 is_sre_generic_instance (MonoClass *class)
9542 init_type_builder_generics (MonoObject *type)
9546 #endif /* !DISABLE_REFLECTION_EMIT */
9550 is_sr_mono_field (MonoClass *class)
9552 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9556 is_sr_mono_property (MonoClass *class)
9558 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9562 is_sr_mono_method (MonoClass *class)
9564 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9568 is_sr_mono_cmethod (MonoClass *class)
9570 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9574 is_sr_mono_generic_method (MonoClass *class)
9576 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9580 is_sr_mono_generic_cmethod (MonoClass *class)
9582 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9586 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9588 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9592 is_usertype (MonoReflectionType *ref)
9594 MonoClass *class = mono_object_class (ref);
9595 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9598 static MonoReflectionType*
9599 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9601 if (!type || type->type)
9604 if (is_usertype (type)) {
9605 type = mono_reflection_type_get_underlying_system_type (type);
9606 if (is_usertype (type))
9607 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9613 * Encode a value in a custom attribute stream of bytes.
9614 * The value to encode is either supplied as an object in argument val
9615 * (valuetypes are boxed), or as a pointer to the data in the
9617 * @type represents the type of the value
9618 * @buffer is the start of the buffer
9619 * @p the current position in the buffer
9620 * @buflen contains the size of the buffer and is used to return the new buffer size
9621 * if this needs to be realloced.
9622 * @retbuffer and @retp return the start and the position of the buffer
9625 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9627 MonoTypeEnum simple_type;
9629 if ((p-buffer) + 10 >= *buflen) {
9632 newbuf = g_realloc (buffer, *buflen);
9633 p = newbuf + (p-buffer);
9637 argval = ((char*)arg + sizeof (MonoObject));
9638 simple_type = type->type;
9640 switch (simple_type) {
9641 case MONO_TYPE_BOOLEAN:
9646 case MONO_TYPE_CHAR:
9649 swap_with_size (p, argval, 2, 1);
9655 swap_with_size (p, argval, 4, 1);
9659 swap_with_size (p, argval, 8, 1);
9664 swap_with_size (p, argval, 8, 1);
9667 case MONO_TYPE_VALUETYPE:
9668 if (type->data.klass->enumtype) {
9669 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9672 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9675 case MONO_TYPE_STRING: {
9682 str = mono_string_to_utf8 ((MonoString*)arg);
9683 slen = strlen (str);
9684 if ((p-buffer) + 10 + slen >= *buflen) {
9688 newbuf = g_realloc (buffer, *buflen);
9689 p = newbuf + (p-buffer);
9692 mono_metadata_encode_value (slen, p, &p);
9693 memcpy (p, str, slen);
9698 case MONO_TYPE_CLASS: {
9706 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9707 slen = strlen (str);
9708 if ((p-buffer) + 10 + slen >= *buflen) {
9712 newbuf = g_realloc (buffer, *buflen);
9713 p = newbuf + (p-buffer);
9716 mono_metadata_encode_value (slen, p, &p);
9717 memcpy (p, str, slen);
9722 case MONO_TYPE_SZARRAY: {
9724 MonoClass *eclass, *arg_eclass;
9727 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9730 len = mono_array_length ((MonoArray*)arg);
9732 *p++ = (len >> 8) & 0xff;
9733 *p++ = (len >> 16) & 0xff;
9734 *p++ = (len >> 24) & 0xff;
9736 *retbuffer = buffer;
9737 eclass = type->data.klass;
9738 arg_eclass = mono_object_class (arg)->element_class;
9741 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9742 eclass = mono_defaults.object_class;
9744 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9745 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9746 int elsize = mono_class_array_element_size (arg_eclass);
9747 for (i = 0; i < len; ++i) {
9748 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9751 } else if (eclass->valuetype && arg_eclass->valuetype) {
9752 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9753 int elsize = mono_class_array_element_size (eclass);
9754 for (i = 0; i < len; ++i) {
9755 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9759 for (i = 0; i < len; ++i) {
9760 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9765 case MONO_TYPE_OBJECT: {
9771 * The parameter type is 'object' but the type of the actual
9772 * argument is not. So we have to add type information to the blob
9773 * too. This is completely undocumented in the spec.
9777 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9782 klass = mono_object_class (arg);
9784 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9787 } else if (klass->enumtype) {
9789 } else if (klass == mono_defaults.string_class) {
9790 simple_type = MONO_TYPE_STRING;
9793 } else if (klass->rank == 1) {
9795 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9796 /* See Partition II, Appendix B3 */
9799 *p++ = klass->element_class->byval_arg.type;
9800 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9802 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9803 *p++ = simple_type = klass->byval_arg.type;
9806 g_error ("unhandled type in custom attr");
9808 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9809 slen = strlen (str);
9810 if ((p-buffer) + 10 + slen >= *buflen) {
9814 newbuf = g_realloc (buffer, *buflen);
9815 p = newbuf + (p-buffer);
9818 mono_metadata_encode_value (slen, p, &p);
9819 memcpy (p, str, slen);
9822 simple_type = mono_class_enum_basetype (klass)->type;
9826 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9829 *retbuffer = buffer;
9833 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9835 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9836 char *str = type_get_qualified_name (type, NULL);
9837 int slen = strlen (str);
9841 * This seems to be optional...
9844 mono_metadata_encode_value (slen, p, &p);
9845 memcpy (p, str, slen);
9848 } else if (type->type == MONO_TYPE_OBJECT) {
9850 } else if (type->type == MONO_TYPE_CLASS) {
9851 /* it should be a type: encode_cattr_value () has the check */
9854 mono_metadata_encode_value (type->type, p, &p);
9855 if (type->type == MONO_TYPE_SZARRAY)
9856 /* See the examples in Partition VI, Annex B */
9857 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9863 #ifndef DISABLE_REFLECTION_EMIT
9865 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9868 /* Preallocate a large enough buffer */
9869 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9870 char *str = type_get_qualified_name (type, NULL);
9873 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9874 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9880 len += strlen (name);
9882 if ((p-buffer) + 20 + len >= *buflen) {
9886 newbuf = g_realloc (buffer, *buflen);
9887 p = newbuf + (p-buffer);
9891 encode_field_or_prop_type (type, p, &p);
9893 len = strlen (name);
9894 mono_metadata_encode_value (len, p, &p);
9895 memcpy (p, name, len);
9897 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9899 *retbuffer = buffer;
9903 * mono_reflection_get_custom_attrs_blob:
9904 * @ctor: custom attribute constructor
9905 * @ctorArgs: arguments o the constructor
9911 * Creates the blob of data that needs to be saved in the metadata and that represents
9912 * the custom attributed described by @ctor, @ctorArgs etc.
9913 * Returns: a Byte array representing the blob of data.
9916 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9919 MonoMethodSignature *sig;
9924 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9925 /* sig is freed later so allocate it in the heap */
9926 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9928 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9931 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9933 p = buffer = g_malloc (buflen);
9934 /* write the prolog */
9937 for (i = 0; i < sig->param_count; ++i) {
9938 arg = mono_array_get (ctorArgs, MonoObject*, i);
9939 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9943 i += mono_array_length (properties);
9945 i += mono_array_length (fields);
9947 *p++ = (i >> 8) & 0xff;
9950 for (i = 0; i < mono_array_length (properties); ++i) {
9954 prop = mono_array_get (properties, gpointer, i);
9955 get_prop_name_and_type (prop, &pname, &ptype);
9956 *p++ = 0x54; /* PROPERTY signature */
9957 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9964 for (i = 0; i < mono_array_length (fields); ++i) {
9968 field = mono_array_get (fields, gpointer, i);
9969 get_field_name_and_type (field, &fname, &ftype);
9970 *p++ = 0x53; /* FIELD signature */
9971 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9976 g_assert (p - buffer <= buflen);
9977 buflen = p - buffer;
9978 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9979 p = mono_array_addr (result, char, 0);
9980 memcpy (p, buffer, buflen);
9982 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9988 * mono_reflection_setup_internal_class:
9989 * @tb: a TypeBuilder object
9991 * Creates a MonoClass that represents the TypeBuilder.
9992 * This is a trick that lets us simplify a lot of reflection code
9993 * (and will allow us to support Build and Run assemblies easier).
9996 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9999 MonoClass *klass, *parent;
10001 RESOLVE_TYPE (tb->parent);
10003 mono_loader_lock ();
10006 /* check so we can compile corlib correctly */
10007 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10008 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10009 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10011 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10017 /* the type has already being created: it means we just have to change the parent */
10018 if (tb->type.type) {
10019 klass = mono_class_from_mono_type (tb->type.type);
10020 klass->parent = NULL;
10021 /* fool mono_class_setup_parent */
10022 klass->supertypes = NULL;
10023 mono_class_setup_parent (klass, parent);
10024 mono_class_setup_mono_type (klass);
10025 mono_loader_unlock ();
10029 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10031 klass->image = &tb->module->dynamic_image->image;
10033 klass->inited = 1; /* we lie to the runtime */
10034 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10035 if (!mono_error_ok (&error))
10037 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10038 if (!mono_error_ok (&error))
10040 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10041 klass->flags = tb->attrs;
10043 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10045 klass->element_class = klass;
10047 if (mono_class_get_ref_info (klass) == NULL) {
10049 mono_class_set_ref_info (klass, tb);
10051 /* Put into cache so mono_class_get_checked () will find it.
10052 Skip nested types as those should not be available on the global scope. */
10053 if (!tb->nesting_type)
10054 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10057 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10058 by performing a mono_class_get which does the full resolution.
10060 Working around this semantics would require us to write a lot of code for no clear advantage.
10062 mono_image_append_class_to_reflection_info_set (klass);
10064 g_assert (mono_class_get_ref_info (klass) == tb);
10067 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10069 if (parent != NULL) {
10070 mono_class_setup_parent (klass, parent);
10071 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10072 const char *old_n = klass->name;
10073 /* trick to get relative numbering right when compiling corlib */
10074 klass->name = "BuildingObject";
10075 mono_class_setup_parent (klass, mono_defaults.object_class);
10076 klass->name = old_n;
10079 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10080 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10081 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10082 klass->instance_size = sizeof (MonoObject);
10083 klass->size_inited = 1;
10084 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10087 mono_class_setup_mono_type (klass);
10089 mono_class_setup_supertypes (klass);
10092 * FIXME: handle interfaces.
10095 tb->type.type = &klass->byval_arg;
10097 if (tb->nesting_type) {
10098 g_assert (tb->nesting_type->type);
10099 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10102 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10104 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10106 mono_loader_unlock ();
10110 mono_loader_unlock ();
10111 mono_error_raise_exception (&error);
10115 * mono_reflection_setup_generic_class:
10116 * @tb: a TypeBuilder object
10118 * Setup the generic class before adding the first generic parameter.
10121 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10126 * mono_reflection_create_generic_class:
10127 * @tb: a TypeBuilder object
10129 * Creates the generic class after all generic parameters have been added.
10132 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10137 klass = mono_class_from_mono_type (tb->type.type);
10139 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10141 if (klass->generic_container || (count == 0))
10144 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10146 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10148 klass->generic_container->owner.klass = klass;
10149 klass->generic_container->type_argc = count;
10150 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10152 klass->is_generic = 1;
10154 for (i = 0; i < count; i++) {
10155 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10156 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10157 klass->generic_container->type_params [i] = *param;
10158 /*Make sure we are a diferent type instance */
10159 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10160 klass->generic_container->type_params [i].info.pklass = NULL;
10161 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10163 g_assert (klass->generic_container->type_params [i].param.owner);
10166 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10170 * mono_reflection_create_internal_class:
10171 * @tb: a TypeBuilder object
10173 * Actually create the MonoClass that is associated with the TypeBuilder.
10176 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10180 klass = mono_class_from_mono_type (tb->type.type);
10182 mono_loader_lock ();
10183 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10184 MonoReflectionFieldBuilder *fb;
10186 MonoType *enum_basetype;
10188 g_assert (tb->fields != NULL);
10189 g_assert (mono_array_length (tb->fields) >= 1);
10191 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10193 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10194 mono_loader_unlock ();
10198 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10199 klass->element_class = mono_class_from_mono_type (enum_basetype);
10200 if (!klass->element_class)
10201 klass->element_class = mono_class_from_mono_type (enum_basetype);
10204 * get the element_class from the current corlib.
10206 ec = default_class_from_mono_type (enum_basetype);
10207 klass->instance_size = ec->instance_size;
10208 klass->size_inited = 1;
10210 * this is almost safe to do with enums and it's needed to be able
10211 * to create objects of the enum type (for use in SetConstant).
10213 /* FIXME: Does this mean enums can't have method overrides ? */
10214 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10216 mono_loader_unlock ();
10219 static MonoMarshalSpec*
10220 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10221 MonoReflectionMarshal *minfo)
10223 MonoMarshalSpec *res;
10225 res = image_g_new0 (image, MonoMarshalSpec, 1);
10226 res->native = minfo->type;
10228 switch (minfo->type) {
10229 case MONO_NATIVE_LPARRAY:
10230 res->data.array_data.elem_type = minfo->eltype;
10231 if (minfo->has_size) {
10232 res->data.array_data.param_num = minfo->param_num;
10233 res->data.array_data.num_elem = minfo->count;
10234 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10237 res->data.array_data.param_num = -1;
10238 res->data.array_data.num_elem = -1;
10239 res->data.array_data.elem_mult = -1;
10243 case MONO_NATIVE_BYVALTSTR:
10244 case MONO_NATIVE_BYVALARRAY:
10245 res->data.array_data.num_elem = minfo->count;
10248 case MONO_NATIVE_CUSTOM:
10249 if (minfo->marshaltyperef)
10250 res->data.custom_data.custom_name =
10251 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10252 if (minfo->mcookie)
10253 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10262 #endif /* !DISABLE_REFLECTION_EMIT */
10264 MonoReflectionMarshalAsAttribute*
10265 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10266 MonoMarshalSpec *spec)
10268 static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10269 MonoReflectionMarshalAsAttribute *minfo;
10272 if (!System_Reflection_Emit_MarshalAsAttribute) {
10273 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10274 mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10275 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10278 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10279 minfo->utype = spec->native;
10281 switch (minfo->utype) {
10282 case MONO_NATIVE_LPARRAY:
10283 minfo->array_subtype = spec->data.array_data.elem_type;
10284 minfo->size_const = spec->data.array_data.num_elem;
10285 if (spec->data.array_data.param_num != -1)
10286 minfo->size_param_index = spec->data.array_data.param_num;
10289 case MONO_NATIVE_BYVALTSTR:
10290 case MONO_NATIVE_BYVALARRAY:
10291 minfo->size_const = spec->data.array_data.num_elem;
10294 case MONO_NATIVE_CUSTOM:
10295 if (spec->data.custom_data.custom_name) {
10296 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10298 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10300 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10302 if (spec->data.custom_data.cookie)
10303 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10313 #ifndef DISABLE_REFLECTION_EMIT
10315 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10316 ReflectionMethodBuilder *rmb,
10317 MonoMethodSignature *sig)
10321 MonoMethodWrapper *wrapperm;
10322 MonoMarshalSpec **specs;
10323 MonoReflectionMethodAux *method_aux;
10328 mono_error_init (&error);
10330 * Methods created using a MethodBuilder should have their memory allocated
10331 * inside the image mempool, while dynamic methods should have their memory
10334 dynamic = rmb->refs != NULL;
10335 image = dynamic ? NULL : klass->image;
10338 g_assert (!klass->generic_class);
10340 mono_loader_lock ();
10342 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10343 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10344 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10346 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10348 wrapperm = (MonoMethodWrapper*)m;
10350 m->dynamic = dynamic;
10352 m->flags = rmb->attrs;
10353 m->iflags = rmb->iattrs;
10354 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10356 m->signature = sig;
10357 m->sre_method = TRUE;
10358 m->skip_visibility = rmb->skip_visibility;
10359 if (rmb->table_idx)
10360 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10362 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10363 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10364 m->string_ctor = 1;
10366 m->signature->pinvoke = 1;
10367 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10368 m->signature->pinvoke = 1;
10370 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10372 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10373 g_assert (mono_error_ok (&error));
10374 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10375 g_assert (mono_error_ok (&error));
10377 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10379 if (image_is_dynamic (klass->image))
10380 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10382 mono_loader_unlock ();
10385 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10386 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10387 MonoMethodHeader *header;
10389 gint32 max_stack, i;
10390 gint32 num_locals = 0;
10391 gint32 num_clauses = 0;
10395 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10396 code_size = rmb->ilgen->code_len;
10397 max_stack = rmb->ilgen->max_stack;
10398 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10399 if (rmb->ilgen->ex_handlers)
10400 num_clauses = method_count_clauses (rmb->ilgen);
10403 code = mono_array_addr (rmb->code, guint8, 0);
10404 code_size = mono_array_length (rmb->code);
10405 /* we probably need to run a verifier on the code... */
10415 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10416 header->code_size = code_size;
10417 header->code = image_g_malloc (image, code_size);
10418 memcpy ((char*)header->code, code, code_size);
10419 header->max_stack = max_stack;
10420 header->init_locals = rmb->init_locals;
10421 header->num_locals = num_locals;
10423 for (i = 0; i < num_locals; ++i) {
10424 MonoReflectionLocalBuilder *lb =
10425 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10427 header->locals [i] = image_g_new0 (image, MonoType, 1);
10428 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10431 header->num_clauses = num_clauses;
10433 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10434 rmb->ilgen, num_clauses);
10437 wrapperm->header = header;
10440 if (rmb->generic_params) {
10441 int count = mono_array_length (rmb->generic_params);
10442 MonoGenericContainer *container = rmb->generic_container;
10444 g_assert (container);
10446 container->type_argc = count;
10447 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10448 container->owner.method = m;
10450 m->is_generic = TRUE;
10451 mono_method_set_generic_container (m, container);
10453 for (i = 0; i < count; i++) {
10454 MonoReflectionGenericParam *gp =
10455 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10456 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10457 container->type_params [i] = *param;
10461 * The method signature might have pointers to generic parameters that belong to other methods.
10462 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10463 * generic parameters.
10465 for (i = 0; i < m->signature->param_count; ++i) {
10466 MonoType *t = m->signature->params [i];
10467 if (t->type == MONO_TYPE_MVAR) {
10468 MonoGenericParam *gparam = t->data.generic_param;
10469 if (gparam->num < count) {
10470 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10471 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10477 if (klass->generic_container) {
10478 container->parent = klass->generic_container;
10479 container->context.class_inst = klass->generic_container->context.class_inst;
10481 container->context.method_inst = mono_get_shared_generic_inst (container);
10485 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10489 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10491 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10492 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10493 for (i = 0; i < rmb->nrefs; ++i)
10494 data [i + 1] = rmb->refs [i];
10499 /* Parameter info */
10502 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10503 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10504 for (i = 0; i <= m->signature->param_count; ++i) {
10505 MonoReflectionParamBuilder *pb;
10506 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10507 if ((i > 0) && (pb->attrs)) {
10508 /* Make a copy since it might point to a shared type structure */
10509 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10510 m->signature->params [i - 1]->attrs = pb->attrs;
10513 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10514 MonoDynamicImage *assembly;
10515 guint32 idx, def_type, len;
10519 if (!method_aux->param_defaults) {
10520 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10521 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10523 assembly = (MonoDynamicImage*)klass->image;
10524 idx = encode_constant (assembly, pb->def_value, &def_type);
10525 /* Copy the data from the blob since it might get realloc-ed */
10526 p = assembly->blob.data + idx;
10527 len = mono_metadata_decode_blob_size (p, &p2);
10529 method_aux->param_defaults [i] = image_g_malloc (image, len);
10530 method_aux->param_default_types [i] = def_type;
10531 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10535 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10536 g_assert (mono_error_ok (&error));
10539 if (!method_aux->param_cattr)
10540 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10541 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10547 /* Parameter marshalling */
10550 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10551 MonoReflectionParamBuilder *pb;
10552 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10553 if (pb->marshal_info) {
10555 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10556 specs [pb->position] =
10557 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10561 if (specs != NULL) {
10563 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10564 method_aux->param_marshall = specs;
10567 if (image_is_dynamic (klass->image) && method_aux)
10568 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10570 mono_loader_unlock ();
10576 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10578 ReflectionMethodBuilder rmb;
10579 MonoMethodSignature *sig;
10581 mono_loader_lock ();
10582 sig = ctor_builder_to_signature (klass->image, mb);
10583 mono_loader_unlock ();
10585 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10587 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10588 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10590 /* If we are in a generic class, we might be called multiple times from inflate_method */
10591 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10592 /* ilgen is no longer needed */
10596 return mb->mhandle;
10600 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10602 ReflectionMethodBuilder rmb;
10603 MonoMethodSignature *sig;
10605 mono_loader_lock ();
10606 sig = method_builder_to_signature (klass->image, mb);
10607 mono_loader_unlock ();
10609 reflection_methodbuilder_from_method_builder (&rmb, mb);
10611 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10612 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10614 /* If we are in a generic class, we might be called multiple times from inflate_method */
10615 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10616 /* ilgen is no longer needed */
10619 return mb->mhandle;
10622 static MonoClassField*
10623 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10625 MonoClassField *field;
10629 field = g_new0 (MonoClassField, 1);
10631 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10632 g_assert (mono_error_ok (&error));
10633 if (fb->attrs || fb->modreq || fb->modopt) {
10634 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10635 field->type->attrs = fb->attrs;
10637 g_assert (image_is_dynamic (klass->image));
10638 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10639 g_free (field->type);
10640 field->type = mono_metadata_type_dup (klass->image, custom);
10643 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10645 if (fb->offset != -1)
10646 field->offset = fb->offset;
10647 field->parent = klass;
10648 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10650 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10657 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10660 MonoReflectionTypeBuilder *tb = NULL;
10661 gboolean is_dynamic = FALSE;
10662 MonoClass *geninst;
10664 mono_loader_lock ();
10666 if (is_sre_type_builder (mono_object_class (type))) {
10667 tb = (MonoReflectionTypeBuilder *) type;
10670 } else if (is_sre_generic_instance (mono_object_class (type))) {
10671 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10672 MonoReflectionType *gtd = rgi->generic_type;
10674 if (is_sre_type_builder (mono_object_class (gtd))) {
10675 tb = (MonoReflectionTypeBuilder *)gtd;
10680 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10681 if (tb && tb->generic_container)
10682 mono_reflection_create_generic_class (tb);
10684 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10685 if (!klass->generic_container) {
10686 mono_loader_unlock ();
10690 if (klass->wastypebuilder) {
10691 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10696 mono_loader_unlock ();
10698 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10700 return &geninst->byval_arg;
10704 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10706 MonoGenericClass *gclass;
10707 MonoGenericInst *inst;
10709 g_assert (klass->generic_container);
10711 inst = mono_metadata_get_generic_inst (type_argc, types);
10712 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10714 return mono_generic_class_get_class (gclass);
10717 MonoReflectionMethod*
10718 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10722 MonoMethod *method, *inflated;
10723 MonoMethodInflated *imethod;
10724 MonoGenericContext tmp_context;
10725 MonoGenericInst *ginst;
10726 MonoType **type_argv;
10729 /*FIXME but this no longer should happen*/
10730 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10731 #ifndef DISABLE_REFLECTION_EMIT
10732 MonoReflectionMethodBuilder *mb = NULL;
10733 MonoReflectionTypeBuilder *tb;
10736 mb = (MonoReflectionMethodBuilder *) rmethod;
10737 tb = (MonoReflectionTypeBuilder *) mb->type;
10738 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10740 method = methodbuilder_to_mono_method (klass, mb);
10742 g_assert_not_reached ();
10746 method = rmethod->method;
10749 klass = method->klass;
10751 if (method->is_inflated)
10752 method = ((MonoMethodInflated *) method)->declaring;
10754 count = mono_method_signature (method)->generic_param_count;
10755 if (count != mono_array_length (types))
10758 type_argv = g_new0 (MonoType *, count);
10759 for (i = 0; i < count; i++) {
10760 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10761 type_argv [i] = mono_reflection_type_get_handle (garg);
10763 ginst = mono_metadata_get_generic_inst (count, type_argv);
10764 g_free (type_argv);
10766 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10767 tmp_context.method_inst = ginst;
10769 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10770 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10771 imethod = (MonoMethodInflated *) inflated;
10773 /*FIXME but I think this is no longer necessary*/
10774 if (image_is_dynamic (method->klass->image)) {
10775 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10777 * This table maps metadata structures representing inflated methods/fields
10778 * to the reflection objects representing their generic definitions.
10780 mono_image_lock ((MonoImage*)image);
10781 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10782 mono_image_unlock ((MonoImage*)image);
10785 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10786 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10788 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10791 #ifndef DISABLE_REFLECTION_EMIT
10793 static MonoMethod *
10794 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10796 MonoMethodInflated *imethod;
10797 MonoGenericContext *context;
10801 * With generic code sharing the klass might not be inflated.
10802 * This can happen because classes inflated with their own
10803 * type arguments are "normalized" to the uninflated class.
10805 if (!klass->generic_class)
10808 context = mono_class_get_context (klass);
10810 if (klass->method.count && klass->methods) {
10811 /* Find the already created inflated method */
10812 for (i = 0; i < klass->method.count; ++i) {
10813 g_assert (klass->methods [i]->is_inflated);
10814 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10817 g_assert (i < klass->method.count);
10818 imethod = (MonoMethodInflated*)klass->methods [i];
10821 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10822 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10825 if (method->is_generic && image_is_dynamic (method->klass->image)) {
10826 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10828 mono_image_lock ((MonoImage*)image);
10829 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10830 mono_image_unlock ((MonoImage*)image);
10832 return (MonoMethod *) imethod;
10835 static MonoMethod *
10836 inflate_method (MonoReflectionType *type, MonoObject *obj)
10838 MonoMethod *method;
10841 MonoClass *type_class = mono_object_class (type);
10843 if (is_sre_generic_instance (type_class)) {
10844 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10845 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10846 } else if (is_sre_type_builder (type_class)) {
10847 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10848 } else if (type->type) {
10849 gklass = mono_class_from_mono_type (type->type);
10850 gklass = mono_class_get_generic_type_definition (gklass);
10852 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10855 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10856 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10857 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10859 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10860 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10861 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10862 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10863 method = ((MonoReflectionMethod *) obj)->method;
10865 method = NULL; /* prevent compiler warning */
10866 g_error ("can't handle type %s", obj->vtable->klass->name);
10869 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10872 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10874 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10876 MonoGenericClass *gclass;
10877 MonoDynamicGenericClass *dgclass;
10878 MonoClass *klass, *gklass;
10882 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10883 klass = mono_class_from_mono_type (gtype);
10884 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10885 gclass = gtype->data.generic_class;
10887 if (!gclass->is_dynamic)
10890 dgclass = (MonoDynamicGenericClass *) gclass;
10892 if (dgclass->initialized)
10895 gklass = gclass->container_class;
10896 mono_class_init (gklass);
10898 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10900 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10901 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10902 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10904 for (i = 0; i < dgclass->count_fields; i++) {
10905 MonoObject *obj = mono_array_get (fields, gpointer, i);
10906 MonoClassField *field, *inflated_field = NULL;
10908 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10909 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10910 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10911 field = ((MonoReflectionField *) obj)->field;
10913 field = NULL; /* prevent compiler warning */
10914 g_assert_not_reached ();
10917 dgclass->fields [i] = *field;
10918 dgclass->fields [i].parent = klass;
10919 dgclass->fields [i].type = mono_class_inflate_generic_type (
10920 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10921 dgclass->field_generic_types [i] = field->type;
10922 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10923 dgclass->field_objects [i] = obj;
10925 if (inflated_field) {
10926 g_free (inflated_field);
10928 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10932 dgclass->initialized = TRUE;
10936 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10938 MonoDynamicGenericClass *dgclass;
10941 g_assert (gclass->is_dynamic);
10943 dgclass = (MonoDynamicGenericClass *)gclass;
10945 for (i = 0; i < dgclass->count_fields; ++i) {
10946 MonoClassField *field = dgclass->fields + i;
10947 mono_metadata_free_type (field->type);
10948 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10953 fix_partial_generic_class (MonoClass *klass)
10955 MonoClass *gklass = klass->generic_class->container_class;
10956 MonoDynamicGenericClass *dgclass;
10959 if (klass->wastypebuilder)
10962 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10963 if (klass->parent != gklass->parent) {
10965 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10966 if (mono_error_ok (&error)) {
10967 MonoClass *parent = mono_class_from_mono_type (parent_type);
10968 mono_metadata_free_type (parent_type);
10969 if (parent != klass->parent) {
10970 /*fool mono_class_setup_parent*/
10971 klass->supertypes = NULL;
10972 mono_class_setup_parent (klass, parent);
10975 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10976 mono_error_cleanup (&error);
10977 if (gklass->wastypebuilder)
10978 klass->wastypebuilder = TRUE;
10983 if (!dgclass->initialized)
10986 if (klass->method.count != gklass->method.count) {
10987 klass->method.count = gklass->method.count;
10988 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10990 for (i = 0; i < klass->method.count; i++) {
10992 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
10993 gklass->methods [i], klass, mono_class_get_context (klass), &error);
10994 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10998 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10999 klass->interface_count = gklass->interface_count;
11000 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11001 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11003 for (i = 0; i < gklass->interface_count; ++i) {
11004 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11005 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11006 mono_metadata_free_type (iface_type);
11008 ensure_runtime_vtable (klass->interfaces [i]);
11010 klass->interfaces_inited = 1;
11013 if (klass->field.count != gklass->field.count) {
11014 klass->field.count = gklass->field.count;
11015 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11017 for (i = 0; i < klass->field.count; i++) {
11018 klass->fields [i] = gklass->fields [i];
11019 klass->fields [i].parent = klass;
11020 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11024 /*We can only finish with this klass once it's parent has as well*/
11025 if (gklass->wastypebuilder)
11026 klass->wastypebuilder = TRUE;
11031 ensure_generic_class_runtime_vtable (MonoClass *klass)
11033 MonoClass *gklass = klass->generic_class->container_class;
11035 ensure_runtime_vtable (gklass);
11037 fix_partial_generic_class (klass);
11041 ensure_runtime_vtable (MonoClass *klass)
11043 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11046 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11049 ensure_runtime_vtable (klass->parent);
11052 num = tb->ctors? mono_array_length (tb->ctors): 0;
11053 num += tb->num_methods;
11054 klass->method.count = num;
11055 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11056 num = tb->ctors? mono_array_length (tb->ctors): 0;
11057 for (i = 0; i < num; ++i)
11058 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11059 num = tb->num_methods;
11061 for (i = 0; i < num; ++i)
11062 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11064 if (tb->interfaces) {
11065 klass->interface_count = mono_array_length (tb->interfaces);
11066 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11067 for (i = 0; i < klass->interface_count; ++i) {
11068 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11069 klass->interfaces [i] = mono_class_from_mono_type (iface);
11070 ensure_runtime_vtable (klass->interfaces [i]);
11072 klass->interfaces_inited = 1;
11074 } else if (klass->generic_class){
11075 ensure_generic_class_runtime_vtable (klass);
11078 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11080 for (i = 0; i < klass->method.count; ++i) {
11081 MonoMethod *im = klass->methods [i];
11082 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11083 im->slot = slot_num++;
11086 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11087 mono_class_setup_interface_offsets (klass);
11088 mono_class_setup_interface_id (klass);
11092 * The generic vtable is needed even if image->run is not set since some
11093 * runtime code like ves_icall_Type_GetMethodsByName depends on
11094 * method->slot being defined.
11098 * tb->methods could not be freed since it is used for determining
11099 * overrides during dynamic vtable construction.
11104 mono_reflection_method_get_handle (MonoObject *method)
11106 MonoClass *class = mono_object_class (method);
11107 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11108 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11109 return sr_method->method;
11111 if (is_sre_method_builder (class)) {
11112 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11113 return mb->mhandle;
11115 if (is_sre_method_on_tb_inst (class)) {
11116 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11117 MonoMethod *result;
11118 /*FIXME move this to a proper method and unify with resolve_object*/
11119 if (m->method_args) {
11120 result = mono_reflection_method_on_tb_inst_get_handle (m);
11122 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11123 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11124 MonoMethod *mono_method;
11126 if (is_sre_method_builder (mono_object_class (m->mb)))
11127 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11128 else if (is_sr_mono_method (mono_object_class (m->mb)))
11129 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11131 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)));
11133 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11138 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11143 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11145 MonoReflectionTypeBuilder *tb;
11147 MonoReflectionMethod *m;
11150 *num_overrides = 0;
11152 g_assert (image_is_dynamic (klass->image));
11154 if (!mono_class_get_ref_info (klass))
11157 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11159 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11163 for (i = 0; i < tb->num_methods; ++i) {
11164 MonoReflectionMethodBuilder *mb =
11165 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11166 if (mb->override_methods)
11167 onum += mono_array_length (mb->override_methods);
11172 *overrides = g_new0 (MonoMethod*, onum * 2);
11175 for (i = 0; i < tb->num_methods; ++i) {
11176 MonoReflectionMethodBuilder *mb =
11177 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11178 if (mb->override_methods) {
11179 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11180 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11182 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11183 (*overrides) [onum * 2 + 1] = mb->mhandle;
11185 g_assert (mb->mhandle);
11193 *num_overrides = onum;
11197 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11199 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11200 MonoReflectionFieldBuilder *fb;
11201 MonoClassField *field;
11202 MonoImage *image = klass->image;
11203 const char *p, *p2;
11205 guint32 len, idx, real_size = 0;
11207 klass->field.count = tb->num_fields;
11208 klass->field.first = 0;
11210 mono_error_init (error);
11212 if (tb->class_size) {
11213 if ((tb->packing_size & 0xffffff00) != 0) {
11214 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11215 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11218 klass->packing_size = tb->packing_size;
11219 real_size = klass->instance_size + tb->class_size;
11222 if (!klass->field.count) {
11223 klass->instance_size = MAX (klass->instance_size, real_size);
11227 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11228 mono_class_alloc_ext (klass);
11229 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11231 This is, guess what, a hack.
11232 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11233 On the static path no field class is resolved, only types are built. This is the right thing to do
11235 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11237 klass->size_inited = 1;
11239 for (i = 0; i < klass->field.count; ++i) {
11240 MonoArray *rva_data;
11241 fb = mono_array_get (tb->fields, gpointer, i);
11242 field = &klass->fields [i];
11243 field->name = mono_string_to_utf8_image (image, fb->name, error);
11244 if (!mono_error_ok (error))
11247 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11248 field->type->attrs = fb->attrs;
11250 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11253 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11254 char *base = mono_array_addr (rva_data, char, 0);
11255 size_t size = mono_array_length (rva_data);
11256 char *data = mono_image_alloc (klass->image, size);
11257 memcpy (data, base, size);
11258 klass->ext->field_def_values [i].data = data;
11260 if (fb->offset != -1)
11261 field->offset = fb->offset;
11262 field->parent = klass;
11263 fb->handle = field;
11264 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11266 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11267 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11269 if (fb->def_value) {
11270 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11271 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11272 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11273 /* Copy the data from the blob since it might get realloc-ed */
11274 p = assembly->blob.data + idx;
11275 len = mono_metadata_decode_blob_size (p, &p2);
11277 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11278 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11282 klass->instance_size = MAX (klass->instance_size, real_size);
11283 mono_class_layout_fields (klass);
11287 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11289 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11290 MonoReflectionPropertyBuilder *pb;
11291 MonoImage *image = klass->image;
11292 MonoProperty *properties;
11295 mono_error_init (error);
11298 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11300 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11301 klass->ext->property.first = 0;
11303 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11304 klass->ext->properties = properties;
11305 for (i = 0; i < klass->ext->property.count; ++i) {
11306 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11307 properties [i].parent = klass;
11308 properties [i].attrs = pb->attrs;
11309 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11310 if (!mono_error_ok (error))
11312 if (pb->get_method)
11313 properties [i].get = pb->get_method->mhandle;
11314 if (pb->set_method)
11315 properties [i].set = pb->set_method->mhandle;
11317 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11318 if (pb->def_value) {
11320 const char *p, *p2;
11321 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11322 if (!klass->ext->prop_def_values)
11323 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11324 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11325 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11326 /* Copy the data from the blob since it might get realloc-ed */
11327 p = assembly->blob.data + idx;
11328 len = mono_metadata_decode_blob_size (p, &p2);
11330 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11331 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11336 MonoReflectionEvent *
11337 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11339 MonoEvent *event = g_new0 (MonoEvent, 1);
11342 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11344 event->parent = klass;
11345 event->attrs = eb->attrs;
11346 event->name = mono_string_to_utf8 (eb->name);
11347 if (eb->add_method)
11348 event->add = eb->add_method->mhandle;
11349 if (eb->remove_method)
11350 event->remove = eb->remove_method->mhandle;
11351 if (eb->raise_method)
11352 event->raise = eb->raise_method->mhandle;
11354 #ifndef MONO_SMALL_CONFIG
11355 if (eb->other_methods) {
11357 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11358 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11359 MonoReflectionMethodBuilder *mb =
11360 mono_array_get (eb->other_methods,
11361 MonoReflectionMethodBuilder*, j);
11362 event->other [j] = mb->mhandle;
11367 return mono_event_get_object (mono_object_domain (tb), klass, event);
11371 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11373 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11374 MonoReflectionEventBuilder *eb;
11375 MonoImage *image = klass->image;
11379 mono_error_init (error);
11382 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11384 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11385 klass->ext->event.first = 0;
11387 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11388 klass->ext->events = events;
11389 for (i = 0; i < klass->ext->event.count; ++i) {
11390 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11391 events [i].parent = klass;
11392 events [i].attrs = eb->attrs;
11393 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11394 if (!mono_error_ok (error))
11396 if (eb->add_method)
11397 events [i].add = eb->add_method->mhandle;
11398 if (eb->remove_method)
11399 events [i].remove = eb->remove_method->mhandle;
11400 if (eb->raise_method)
11401 events [i].raise = eb->raise_method->mhandle;
11403 #ifndef MONO_SMALL_CONFIG
11404 if (eb->other_methods) {
11406 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11407 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11408 MonoReflectionMethodBuilder *mb =
11409 mono_array_get (eb->other_methods,
11410 MonoReflectionMethodBuilder*, j);
11411 events [i].other [j] = mb->mhandle;
11415 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11420 remove_instantiations_of_and_ensure_contents (gpointer key,
11422 gpointer user_data)
11424 MonoType *type = (MonoType*)key;
11425 MonoClass *klass = (MonoClass*)user_data;
11427 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11428 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11435 check_array_for_usertypes (MonoArray *arr)
11442 for (i = 0; i < mono_array_length (arr); ++i)
11443 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11446 MonoReflectionType*
11447 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11451 MonoDomain* domain;
11452 MonoReflectionType* res;
11455 domain = mono_object_domain (tb);
11456 klass = mono_class_from_mono_type (tb->type.type);
11459 * Check for user defined Type subclasses.
11461 RESOLVE_TYPE (tb->parent);
11462 check_array_for_usertypes (tb->interfaces);
11464 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11465 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11467 RESOLVE_TYPE (fb->type);
11468 check_array_for_usertypes (fb->modreq);
11469 check_array_for_usertypes (fb->modopt);
11470 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11471 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11476 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11477 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11479 RESOLVE_TYPE (mb->rtype);
11480 check_array_for_usertypes (mb->return_modreq);
11481 check_array_for_usertypes (mb->return_modopt);
11482 check_array_for_usertypes (mb->parameters);
11483 if (mb->param_modreq)
11484 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11485 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11486 if (mb->param_modopt)
11487 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11488 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11493 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11494 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11496 check_array_for_usertypes (mb->parameters);
11497 if (mb->param_modreq)
11498 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11499 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11500 if (mb->param_modopt)
11501 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11502 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11507 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11510 * we need to lock the domain because the lock will be taken inside
11511 * So, we need to keep the locking order correct.
11513 mono_loader_lock ();
11514 mono_domain_lock (domain);
11515 if (klass->wastypebuilder) {
11516 mono_domain_unlock (domain);
11517 mono_loader_unlock ();
11518 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11521 * Fields to set in klass:
11522 * the various flags: delegate/unicode/contextbound etc.
11524 klass->flags = tb->attrs;
11525 klass->has_cctor = 1;
11526 klass->has_finalize = 1;
11527 klass->has_finalize_inited = 1;
11529 mono_class_setup_parent (klass, klass->parent);
11530 /* fool mono_class_setup_supertypes */
11531 klass->supertypes = NULL;
11532 mono_class_setup_supertypes (klass);
11533 mono_class_setup_mono_type (klass);
11536 if (!((MonoDynamicImage*)klass->image)->run) {
11537 if (klass->generic_container) {
11538 /* FIXME: The code below can't handle generic classes */
11539 klass->wastypebuilder = TRUE;
11540 mono_loader_unlock ();
11541 mono_domain_unlock (domain);
11542 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11547 /* enums are done right away */
11548 if (!klass->enumtype)
11549 ensure_runtime_vtable (klass);
11551 if (tb->subtypes) {
11552 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11553 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11554 mono_class_alloc_ext (klass);
11555 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)));
11559 klass->nested_classes_inited = TRUE;
11561 /* fields and object layout */
11562 if (klass->parent) {
11563 if (!klass->parent->size_inited)
11564 mono_class_init (klass->parent);
11565 klass->instance_size = klass->parent->instance_size;
11566 klass->sizes.class_size = 0;
11567 klass->min_align = klass->parent->min_align;
11568 /* if the type has no fields we won't call the field_setup
11569 * routine which sets up klass->has_references.
11571 klass->has_references |= klass->parent->has_references;
11573 klass->instance_size = sizeof (MonoObject);
11574 klass->min_align = 1;
11577 /* FIXME: handle packing_size and instance_size */
11578 typebuilder_setup_fields (klass, &error);
11579 if (!mono_error_ok (&error))
11581 typebuilder_setup_properties (klass, &error);
11582 if (!mono_error_ok (&error))
11585 typebuilder_setup_events (klass, &error);
11586 if (!mono_error_ok (&error))
11589 klass->wastypebuilder = TRUE;
11592 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11593 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11594 * we want to return normal System.MonoType objects, so clear these out from the cache.
11596 * Together with this we must ensure the contents of all instances to match the created type.
11598 if (domain->type_hash && klass->generic_container)
11599 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11601 mono_domain_unlock (domain);
11602 mono_loader_unlock ();
11604 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11605 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11606 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11609 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11610 g_assert (res != (MonoReflectionType*)tb);
11615 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11616 klass->wastypebuilder = TRUE;
11617 mono_domain_unlock (domain);
11618 mono_loader_unlock ();
11619 mono_error_raise_exception (&error);
11624 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11626 MonoGenericParamFull *param;
11631 image = &gparam->tbuilder->module->dynamic_image->image;
11633 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11635 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11636 g_assert (mono_error_ok (&error));
11637 param->param.num = gparam->index;
11639 if (gparam->mbuilder) {
11640 if (!gparam->mbuilder->generic_container) {
11641 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11642 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11643 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11644 gparam->mbuilder->generic_container->is_method = TRUE;
11646 * Cannot set owner.method, since the MonoMethod is not created yet.
11647 * Set the image field instead, so type_in_image () works.
11649 gparam->mbuilder->generic_container->image = klass->image;
11651 param->param.owner = gparam->mbuilder->generic_container;
11652 } else if (gparam->tbuilder) {
11653 if (!gparam->tbuilder->generic_container) {
11654 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11655 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11656 gparam->tbuilder->generic_container->owner.klass = klass;
11658 param->param.owner = gparam->tbuilder->generic_container;
11661 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11663 gparam->type.type = &pklass->byval_arg;
11665 mono_class_set_ref_info (pklass, gparam);
11666 mono_image_append_class_to_reflection_info_set (pklass);
11670 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11672 MonoReflectionModuleBuilder *module = sig->module;
11673 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11674 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11679 check_array_for_usertypes (sig->arguments);
11681 sigbuffer_init (&buf, 32);
11683 sigbuffer_add_value (&buf, 0x07);
11684 sigbuffer_add_value (&buf, na);
11685 if (assembly != NULL){
11686 for (i = 0; i < na; ++i) {
11687 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11688 encode_reflection_type (assembly, type, &buf);
11692 buflen = buf.p - buf.buf;
11693 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11694 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11695 sigbuffer_free (&buf);
11701 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11703 MonoDynamicImage *assembly = sig->module->dynamic_image;
11704 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11709 check_array_for_usertypes (sig->arguments);
11711 sigbuffer_init (&buf, 32);
11713 sigbuffer_add_value (&buf, 0x06);
11714 for (i = 0; i < na; ++i) {
11715 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11716 encode_reflection_type (assembly, type, &buf);
11719 buflen = buf.p - buf.buf;
11720 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11721 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11722 sigbuffer_free (&buf);
11728 MonoMethod *handle;
11729 MonoDomain *domain;
11730 } DynamicMethodReleaseData;
11733 * The runtime automatically clean up those after finalization.
11735 static MonoReferenceQueue *dynamic_method_queue;
11738 free_dynamic_method (void *dynamic_method)
11740 DynamicMethodReleaseData *data = dynamic_method;
11742 mono_runtime_free_method (data->domain, data->handle);
11747 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11749 MonoReferenceQueue *queue;
11750 MonoMethod *handle;
11751 DynamicMethodReleaseData *release_data;
11752 ReflectionMethodBuilder rmb;
11753 MonoMethodSignature *sig;
11758 if (mono_runtime_is_shutting_down ())
11759 mono_raise_exception (mono_get_exception_invalid_operation (""));
11761 if (!(queue = dynamic_method_queue)) {
11762 mono_loader_lock ();
11763 if (!(queue = dynamic_method_queue))
11764 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11765 mono_loader_unlock ();
11768 sig = dynamic_method_to_signature (mb);
11770 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11773 * Resolve references.
11776 * Every second entry in the refs array is reserved for storing handle_class,
11777 * which is needed by the ldtoken implementation in the JIT.
11779 rmb.nrefs = mb->nrefs;
11780 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11781 for (i = 0; i < mb->nrefs; i += 2) {
11782 MonoClass *handle_class;
11784 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11786 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11787 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11789 * The referenced DynamicMethod should already be created by the managed
11790 * code, except in the case of circular references. In that case, we store
11791 * method in the refs array, and fix it up later when the referenced
11792 * DynamicMethod is created.
11794 if (method->mhandle) {
11795 ref = method->mhandle;
11797 /* FIXME: GC object stored in unmanaged memory */
11800 /* FIXME: GC object stored in unmanaged memory */
11801 method->referenced_by = g_slist_append (method->referenced_by, mb);
11803 handle_class = mono_defaults.methodhandle_class;
11805 MonoException *ex = NULL;
11806 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11808 ex = mono_get_exception_type_load (NULL, NULL);
11809 else if (mono_security_core_clr_enabled ())
11810 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11814 mono_raise_exception (ex);
11819 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11820 rmb.refs [i + 1] = handle_class;
11823 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11825 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11826 release_data = g_new (DynamicMethodReleaseData, 1);
11827 release_data->handle = handle;
11828 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11829 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11830 g_free (release_data);
11832 /* Fix up refs entries pointing at us */
11833 for (l = mb->referenced_by; l; l = l->next) {
11834 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11835 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11838 g_assert (method->mhandle);
11840 data = (gpointer*)wrapper->method_data;
11841 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11842 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11843 data [i + 1] = mb->mhandle;
11846 g_slist_free (mb->referenced_by);
11850 /* ilgen is no longer needed */
11854 #endif /* DISABLE_REFLECTION_EMIT */
11858 * mono_reflection_is_valid_dynamic_token:
11860 * Returns TRUE if token is valid.
11864 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11866 return lookup_dyn_token (image, token) != NULL;
11869 MonoMethodSignature *
11870 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
11872 MonoMethodSignature *sig;
11873 g_assert (image_is_dynamic (image));
11875 mono_error_init (error);
11877 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11881 return mono_method_signature_checked (method, error);
11884 #ifndef DISABLE_REFLECTION_EMIT
11887 * mono_reflection_lookup_dynamic_token:
11889 * Finish the Builder object pointed to by TOKEN and return the corresponding
11890 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11891 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11894 * LOCKING: Take the loader lock
11897 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11899 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11903 obj = lookup_dyn_token (assembly, token);
11906 g_error ("Could not find required dynamic token 0x%08x", token);
11912 handle_class = &klass;
11913 return resolve_object (image, obj, handle_class, context);
11917 * ensure_complete_type:
11919 * Ensure that KLASS is completed if it is a dynamic type, or references
11923 ensure_complete_type (MonoClass *klass)
11925 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11926 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11928 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11930 // Asserting here could break a lot of code
11931 //g_assert (klass->wastypebuilder);
11934 if (klass->generic_class) {
11935 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11938 for (i = 0; i < inst->type_argc; ++i) {
11939 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11945 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11947 gpointer result = NULL;
11949 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11950 result = mono_string_intern ((MonoString*)obj);
11951 *handle_class = mono_defaults.string_class;
11953 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11954 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11955 MonoClass *mc = mono_class_from_mono_type (type);
11956 if (!mono_class_init (mc))
11957 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11960 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11961 result = mono_class_from_mono_type (inflated);
11962 mono_metadata_free_type (inflated);
11964 result = mono_class_from_mono_type (type);
11966 *handle_class = mono_defaults.typehandle_class;
11968 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11969 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11970 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11971 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11972 result = ((MonoReflectionMethod*)obj)->method;
11975 result = mono_class_inflate_generic_method_checked (result, context, &error);
11976 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11978 *handle_class = mono_defaults.methodhandle_class;
11980 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11981 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11982 result = mb->mhandle;
11984 /* Type is not yet created */
11985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11987 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11990 * Hopefully this has been filled in by calling CreateType() on the
11994 * TODO: This won't work if the application finishes another
11995 * TypeBuilder instance instead of this one.
11997 result = mb->mhandle;
12001 result = mono_class_inflate_generic_method_checked (result, context, &error);
12002 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12004 *handle_class = mono_defaults.methodhandle_class;
12005 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12006 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12008 result = cb->mhandle;
12010 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12012 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12013 result = cb->mhandle;
12017 result = mono_class_inflate_generic_method_checked (result, context, &error);
12018 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12020 *handle_class = mono_defaults.methodhandle_class;
12021 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12022 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12024 ensure_complete_type (field->parent);
12026 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12027 MonoClass *class = mono_class_from_mono_type (inflated);
12028 MonoClassField *inflated_field;
12029 gpointer iter = NULL;
12030 mono_metadata_free_type (inflated);
12031 while ((inflated_field = mono_class_get_fields (class, &iter))) {
12032 if (!strcmp (field->name, inflated_field->name))
12035 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12036 result = inflated_field;
12040 *handle_class = mono_defaults.fieldhandle_class;
12042 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12043 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12044 result = fb->handle;
12047 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12049 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12050 result = fb->handle;
12053 if (fb->handle && fb->handle->parent->generic_container) {
12054 MonoClass *klass = fb->handle->parent;
12055 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12056 MonoClass *inflated = mono_class_from_mono_type (type);
12058 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12060 mono_metadata_free_type (type);
12062 *handle_class = mono_defaults.fieldhandle_class;
12063 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12064 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12065 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
12068 klass = type->data.klass;
12069 if (klass->wastypebuilder) {
12070 /* Already created */
12074 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12075 result = type->data.klass;
12078 *handle_class = mono_defaults.typehandle_class;
12079 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12080 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12081 MonoMethodSignature *sig;
12084 if (helper->arguments)
12085 nargs = mono_array_length (helper->arguments);
12089 sig = mono_metadata_signature_alloc (image, nargs);
12090 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12091 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12093 if (helper->unmanaged_call_conv) { /* unmanaged */
12094 sig->call_convention = helper->unmanaged_call_conv - 1;
12095 sig->pinvoke = TRUE;
12096 } else if (helper->call_conv & 0x02) {
12097 sig->call_convention = MONO_CALL_VARARG;
12099 sig->call_convention = MONO_CALL_DEFAULT;
12102 sig->param_count = nargs;
12103 /* TODO: Copy type ? */
12104 sig->ret = helper->return_type->type;
12105 for (i = 0; i < nargs; ++i)
12106 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12109 *handle_class = NULL;
12110 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12111 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12112 /* Already created by the managed code */
12113 g_assert (method->mhandle);
12114 result = method->mhandle;
12115 *handle_class = mono_defaults.methodhandle_class;
12116 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12117 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12118 type = mono_class_inflate_generic_type (type, context);
12119 result = mono_class_from_mono_type (type);
12120 *handle_class = mono_defaults.typehandle_class;
12122 mono_metadata_free_type (type);
12123 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12124 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12125 type = mono_class_inflate_generic_type (type, context);
12126 result = mono_class_from_mono_type (type);
12127 *handle_class = mono_defaults.typehandle_class;
12129 mono_metadata_free_type (type);
12130 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12131 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12132 MonoClass *inflated;
12134 MonoClassField *field;
12136 if (is_sre_field_builder (mono_object_class (f->fb)))
12137 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12138 else if (is_sr_mono_field (mono_object_class (f->fb)))
12139 field = ((MonoReflectionField*)f->fb)->field;
12141 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)));
12143 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12144 inflated = mono_class_from_mono_type (type);
12146 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12147 ensure_complete_type (field->parent);
12149 mono_metadata_free_type (type);
12150 *handle_class = mono_defaults.fieldhandle_class;
12151 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12152 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12153 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12154 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12155 MonoMethod *method;
12157 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12158 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12159 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12160 method = ((MonoReflectionMethod *)c->cb)->method;
12162 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)));
12164 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12165 *handle_class = mono_defaults.methodhandle_class;
12166 mono_metadata_free_type (type);
12167 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12168 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12169 if (m->method_args) {
12170 result = mono_reflection_method_on_tb_inst_get_handle (m);
12173 result = mono_class_inflate_generic_method_checked (result, context, &error);
12174 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12177 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12178 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12179 MonoMethod *method;
12181 if (is_sre_method_builder (mono_object_class (m->mb)))
12182 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12183 else if (is_sr_mono_method (mono_object_class (m->mb)))
12184 method = ((MonoReflectionMethod *)m->mb)->method;
12186 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)));
12188 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12189 mono_metadata_free_type (type);
12191 *handle_class = mono_defaults.methodhandle_class;
12192 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12193 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12196 MonoMethod *method;
12200 mtype = mono_reflection_type_get_handle (m->parent);
12201 klass = mono_class_from_mono_type (mtype);
12203 /* Find the method */
12205 name = mono_string_to_utf8 (m->name);
12207 while ((method = mono_class_get_methods (klass, &iter))) {
12208 if (!strcmp (method->name, name))
12215 // FIXME: Check parameters/return value etc. match
12218 *handle_class = mono_defaults.methodhandle_class;
12219 } else if (is_sre_array (mono_object_get_class(obj)) ||
12220 is_sre_byref (mono_object_get_class(obj)) ||
12221 is_sre_pointer (mono_object_get_class(obj))) {
12222 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12223 MonoType *type = mono_reflection_type_get_handle (ref_type);
12226 MonoType *inflated = mono_class_inflate_generic_type (type, context);
12227 result = mono_class_from_mono_type (inflated);
12228 mono_metadata_free_type (inflated);
12230 result = mono_class_from_mono_type (type);
12232 *handle_class = mono_defaults.typehandle_class;
12234 g_print ("%s\n", obj->vtable->klass->name);
12235 g_assert_not_reached ();
12240 #else /* DISABLE_REFLECTION_EMIT */
12243 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
12245 g_assert_not_reached ();
12250 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12252 g_assert_not_reached ();
12256 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12258 g_assert_not_reached ();
12262 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12264 g_assert_not_reached ();
12268 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12270 g_assert_not_reached ();
12274 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12276 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12280 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12282 g_assert_not_reached ();
12286 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12288 g_assert_not_reached ();
12291 MonoReflectionModule *
12292 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12294 g_assert_not_reached ();
12299 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12301 g_assert_not_reached ();
12306 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12308 g_assert_not_reached ();
12313 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12314 gboolean create_open_instance, gboolean register_token)
12316 g_assert_not_reached ();
12321 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12326 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12328 g_assert_not_reached ();
12332 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12335 *num_overrides = 0;
12338 MonoReflectionEvent *
12339 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12341 g_assert_not_reached ();
12345 MonoReflectionType*
12346 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12348 g_assert_not_reached ();
12353 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12355 g_assert_not_reached ();
12359 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12361 g_assert_not_reached ();
12366 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12368 g_assert_not_reached ();
12373 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12378 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12384 mono_reflection_type_get_handle (MonoReflectionType* ref)
12392 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12394 g_assert_not_reached ();
12397 #endif /* DISABLE_REFLECTION_EMIT */
12399 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12400 const static guint32 declsec_flags_map[] = {
12401 0x00000000, /* empty */
12402 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12403 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12404 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12405 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12406 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12407 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12408 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12409 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12410 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12411 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12412 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12413 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12414 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12415 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12416 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12417 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12418 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12419 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12423 * Returns flags that includes all available security action associated to the handle.
12424 * @token: metadata token (either for a class or a method)
12425 * @image: image where resides the metadata.
12428 mono_declsec_get_flags (MonoImage *image, guint32 token)
12430 int index = mono_metadata_declsec_from_index (image, token);
12431 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12432 guint32 result = 0;
12436 /* HasSecurity can be present for other, not specially encoded, attributes,
12437 e.g. SuppressUnmanagedCodeSecurityAttribute */
12441 for (i = index; i < t->rows; i++) {
12442 guint32 cols [MONO_DECL_SECURITY_SIZE];
12444 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12445 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12448 action = cols [MONO_DECL_SECURITY_ACTION];
12449 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12450 result |= declsec_flags_map [action];
12452 g_assert_not_reached ();
12459 * Get the security actions (in the form of flags) associated with the specified method.
12461 * @method: The method for which we want the declarative security flags.
12462 * Return the declarative security flags for the method (only).
12464 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12465 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12468 mono_declsec_flags_from_method (MonoMethod *method)
12470 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12471 /* FIXME: No cache (for the moment) */
12472 guint32 idx = mono_method_get_index (method);
12473 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12474 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12475 return mono_declsec_get_flags (method->klass->image, idx);
12481 * Get the security actions (in the form of flags) associated with the specified class.
12483 * @klass: The class for which we want the declarative security flags.
12484 * Return the declarative security flags for the class.
12486 * Note: We cache the flags inside the MonoClass structure as this will get
12487 * called very often (at least for each method).
12490 mono_declsec_flags_from_class (MonoClass *klass)
12492 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12493 if (!klass->ext || !klass->ext->declsec_flags) {
12496 idx = mono_metadata_token_index (klass->type_token);
12497 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12498 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12499 mono_loader_lock ();
12500 mono_class_alloc_ext (klass);
12501 mono_loader_unlock ();
12502 /* we cache the flags on classes */
12503 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12505 return klass->ext->declsec_flags;
12511 * Get the security actions (in the form of flags) associated with the specified assembly.
12513 * @assembly: The assembly for which we want the declarative security flags.
12514 * Return the declarative security flags for the assembly.
12517 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12519 guint32 idx = 1; /* there is only one assembly */
12520 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12521 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12522 return mono_declsec_get_flags (assembly->image, idx);
12527 * Fill actions for the specific index (which may either be an encoded class token or
12528 * an encoded method token) from the metadata image.
12529 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12532 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12533 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12535 MonoBoolean result = FALSE;
12537 guint32 cols [MONO_DECL_SECURITY_SIZE];
12538 int index = mono_metadata_declsec_from_index (image, token);
12541 t = &image->tables [MONO_TABLE_DECLSECURITY];
12542 for (i = index; i < t->rows; i++) {
12543 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12545 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12548 /* if present only replace (class) permissions with method permissions */
12549 /* if empty accept either class or method permissions */
12550 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12551 if (!actions->demand.blob) {
12552 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12553 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12554 actions->demand.blob = (char*) (blob + 2);
12555 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12558 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12559 if (!actions->noncasdemand.blob) {
12560 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12561 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12562 actions->noncasdemand.blob = (char*) (blob + 2);
12563 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12566 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12567 if (!actions->demandchoice.blob) {
12568 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12569 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12570 actions->demandchoice.blob = (char*) (blob + 2);
12571 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12581 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12582 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12584 guint32 idx = mono_metadata_token_index (klass->type_token);
12585 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12586 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12587 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12591 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12592 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12594 guint32 idx = mono_method_get_index (method);
12595 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12596 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12597 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12601 * Collect all actions (that requires to generate code in mini) assigned for
12602 * the specified method.
12603 * Note: Don't use the content of actions if the function return FALSE.
12606 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12608 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12609 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12610 MonoBoolean result = FALSE;
12613 /* quick exit if no declarative security is present in the metadata */
12614 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12617 /* we want the original as the wrapper is "free" of the security informations */
12618 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12619 method = mono_marshal_method_from_wrapper (method);
12624 /* First we look for method-level attributes */
12625 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12626 mono_class_init (method->klass);
12627 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12629 result = mono_declsec_get_method_demands_params (method, demands,
12630 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12633 /* Here we use (or create) the class declarative cache to look for demands */
12634 flags = mono_declsec_flags_from_class (method->klass);
12635 if (flags & mask) {
12637 mono_class_init (method->klass);
12638 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12640 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12641 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12644 /* The boolean return value is used as a shortcut in case nothing needs to
12645 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12651 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12653 * Note: Don't use the content of actions if the function return FALSE.
12656 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12658 MonoBoolean result = FALSE;
12661 /* quick exit if no declarative security is present in the metadata */
12662 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12665 /* we want the original as the wrapper is "free" of the security informations */
12666 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12667 method = mono_marshal_method_from_wrapper (method);
12672 /* results are independant - zeroize both */
12673 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12674 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12676 /* First we look for method-level attributes */
12677 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12678 mono_class_init (method->klass);
12680 result = mono_declsec_get_method_demands_params (method, cmethod,
12681 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12684 /* Here we use (or create) the class declarative cache to look for demands */
12685 flags = mono_declsec_flags_from_class (method->klass);
12686 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12687 mono_class_init (method->klass);
12689 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12690 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12697 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12699 * @klass The inherited class - this is the class that provides the security check (attributes)
12701 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12703 * Note: Don't use the content of actions if the function return FALSE.
12706 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12708 MonoBoolean result = FALSE;
12711 /* quick exit if no declarative security is present in the metadata */
12712 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12715 /* Here we use (or create) the class declarative cache to look for demands */
12716 flags = mono_declsec_flags_from_class (klass);
12717 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12718 mono_class_init (klass);
12719 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12721 result |= mono_declsec_get_class_demands_params (klass, demands,
12722 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12729 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12731 * Note: Don't use the content of actions if the function return FALSE.
12734 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12736 /* quick exit if no declarative security is present in the metadata */
12737 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12740 /* we want the original as the wrapper is "free" of the security informations */
12741 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12742 method = mono_marshal_method_from_wrapper (method);
12747 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12748 mono_class_init (method->klass);
12749 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12751 return mono_declsec_get_method_demands_params (method, demands,
12752 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12759 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12761 guint32 cols [MONO_DECL_SECURITY_SIZE];
12765 int index = mono_metadata_declsec_from_index (image, token);
12769 t = &image->tables [MONO_TABLE_DECLSECURITY];
12770 for (i = index; i < t->rows; i++) {
12771 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12773 /* shortcut - index are ordered */
12774 if (token != cols [MONO_DECL_SECURITY_PARENT])
12777 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12778 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12779 entry->blob = (char*) (metadata + 2);
12780 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12789 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12791 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12792 guint32 idx = mono_method_get_index (method);
12793 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12794 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12795 return get_declsec_action (method->klass->image, idx, action, entry);
12801 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12804 guint32 flags = mono_declsec_flags_from_class (klass);
12805 if (declsec_flags_map [action] & flags) {
12806 guint32 idx = mono_metadata_token_index (klass->type_token);
12807 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12808 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12809 return get_declsec_action (klass->image, idx, action, entry);
12815 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12817 guint32 idx = 1; /* there is only one assembly */
12818 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12819 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12821 return get_declsec_action (assembly->image, idx, action, entry);
12825 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12827 MonoObject *res, *exc;
12829 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12830 static MonoMethod *method = NULL;
12832 if (!System_Reflection_Emit_TypeBuilder) {
12833 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12834 g_assert (System_Reflection_Emit_TypeBuilder);
12836 if (method == NULL) {
12837 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12842 * The result of mono_type_get_object () might be a System.MonoType but we
12843 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12845 g_assert (mono_class_get_ref_info (klass));
12846 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12848 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12850 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12854 return *(MonoBoolean*)mono_object_unbox (res);
12858 * mono_reflection_type_get_type:
12859 * @reftype: the System.Type object
12861 * Returns the MonoType* associated with the C# System.Type object @reftype.
12864 mono_reflection_type_get_type (MonoReflectionType *reftype)
12866 g_assert (reftype);
12868 return mono_reflection_type_get_handle (reftype);
12872 * mono_reflection_assembly_get_assembly:
12873 * @refassembly: the System.Reflection.Assembly object
12875 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12878 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12880 g_assert (refassembly);
12882 return refassembly->assembly;