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)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do { \
50 if (!reflection_info_desc) { \
52 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
54 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
57 #define MOVING_GC_REGISTER(addr)
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA 0x00002000
76 MonoReflectionILGen *ilgen;
77 MonoReflectionType *rtype;
78 MonoArray *parameters;
79 MonoArray *generic_params;
80 MonoGenericContainer *generic_container;
86 guint32 *table_idx; /* note: it's a pointer */
90 MonoBoolean init_locals;
91 MonoBoolean skip_visibility;
92 MonoArray *return_modreq;
93 MonoArray *return_modopt;
94 MonoArray *param_modreq;
95 MonoArray *param_modopt;
96 MonoArray *permissions;
101 int charset, extra_flags, native_cc;
102 MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
107 MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
120 MONO_INTERFACEIMPL_SIZE,
121 MONO_MEMBERREF_SIZE, /* 0x0A */
123 MONO_CUSTOM_ATTR_SIZE,
124 MONO_FIELD_MARSHAL_SIZE,
125 MONO_DECL_SECURITY_SIZE,
126 MONO_CLASS_LAYOUT_SIZE,
127 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128 MONO_STAND_ALONE_SIGNATURE_SIZE,
132 MONO_PROPERTY_MAP_SIZE,
135 MONO_METHOD_SEMA_SIZE,
136 MONO_METHODIMPL_SIZE,
137 MONO_MODULEREF_SIZE, /* 0x1A */
143 MONO_ASSEMBLY_SIZE, /* 0x20 */
144 MONO_ASSEMBLY_PROCESSOR_SIZE,
145 MONO_ASSEMBLYOS_SIZE,
146 MONO_ASSEMBLYREF_SIZE,
147 MONO_ASSEMBLYREFPROC_SIZE,
148 MONO_ASSEMBLYREFOS_SIZE,
152 MONO_NESTED_CLASS_SIZE,
154 MONO_GENERICPARAM_SIZE, /* 0x2A */
155 MONO_METHODSPEC_SIZE,
156 MONO_GENPARCONSTRAINT_SIZE
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
206 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
207 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
208 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
209 __type = mono_reflection_type_resolve_user_types (__type); \
210 mono_array_set (arr, MonoReflectionType*, index, __type); \
213 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
216 mono_reflection_init (void)
221 sigbuffer_init (SigBuffer *buf, int size)
223 buf->buf = g_malloc (size);
225 buf->end = buf->buf + size;
229 sigbuffer_make_room (SigBuffer *buf, int size)
231 if (buf->end - buf->p < size) {
232 int new_size = buf->end - buf->buf + size + 32;
233 char *p = g_realloc (buf->buf, new_size);
234 size = buf->p - buf->buf;
237 buf->end = buf->buf + new_size;
242 sigbuffer_add_value (SigBuffer *buf, guint32 val)
244 sigbuffer_make_room (buf, 6);
245 mono_metadata_encode_value (val, buf->p, &buf->p);
249 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
251 sigbuffer_make_room (buf, 1);
257 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
259 sigbuffer_make_room (buf, size);
260 memcpy (buf->p, p, size);
265 sigbuffer_free (SigBuffer *buf)
270 #ifndef DISABLE_REFLECTION_EMIT
274 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
278 image_g_malloc (MonoImage *image, guint size)
281 return mono_image_alloc (image, size);
283 return g_malloc (size);
285 #endif /* !DISABLE_REFLECTION_EMIT */
290 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
294 image_g_malloc0 (MonoImage *image, guint size)
297 return mono_image_alloc0 (image, size);
299 return g_malloc0 (size);
302 #ifndef DISABLE_REFLECTION_EMIT
304 image_strdup (MonoImage *image, const char *s)
307 return mono_image_strdup (image, s);
313 #define image_g_new(image,struct_type, n_structs) \
314 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
316 #define image_g_new0(image,struct_type, n_structs) \
317 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
321 alloc_table (MonoDynamicTable *table, guint nrows)
324 g_assert (table->columns);
325 if (nrows + 1 >= table->alloc_rows) {
326 while (nrows + 1 >= table->alloc_rows) {
327 if (table->alloc_rows == 0)
328 table->alloc_rows = 16;
330 table->alloc_rows *= 2;
333 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
338 make_room_in_stream (MonoDynamicStream *stream, int size)
340 if (size <= stream->alloc_size)
343 while (stream->alloc_size <= size) {
344 if (stream->alloc_size < 4096)
345 stream->alloc_size = 4096;
347 stream->alloc_size *= 2;
350 stream->data = g_realloc (stream->data, stream->alloc_size);
354 string_heap_insert (MonoDynamicStream *sh, const char *str)
358 gpointer oldkey, oldval;
360 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
361 return GPOINTER_TO_UINT (oldval);
363 len = strlen (str) + 1;
366 make_room_in_stream (sh, idx + len);
369 * We strdup the string even if we already copy them in sh->data
370 * so that the string pointers in the hash remain valid even if
371 * we need to realloc sh->data. We may want to avoid that later.
373 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
374 memcpy (sh->data + idx, str, len);
380 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
382 char *name = mono_string_to_utf8 (str);
384 idx = string_heap_insert (sh, name);
389 #ifndef DISABLE_REFLECTION_EMIT
391 string_heap_init (MonoDynamicStream *sh)
394 sh->alloc_size = 4096;
395 sh->data = g_malloc (4096);
396 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
397 string_heap_insert (sh, "");
402 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
406 make_room_in_stream (stream, stream->index + len);
407 memcpy (stream->data + stream->index, data, len);
409 stream->index += len;
411 * align index? Not without adding an additional param that controls it since
412 * we may store a blob value in pieces.
418 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
422 make_room_in_stream (stream, stream->index + len);
423 memset (stream->data + stream->index, 0, len);
425 stream->index += len;
430 stream_data_align (MonoDynamicStream *stream)
433 guint32 count = stream->index % 4;
435 /* we assume the stream data will be aligned */
437 mono_image_add_stream_data (stream, buf, 4 - count);
440 #ifndef DISABLE_REFLECTION_EMIT
442 mono_blob_entry_hash (const char* str)
446 len = mono_metadata_decode_blob_size (str, &str);
450 for (str += 1; str < end; str++)
451 h = (h << 5) - h + *str;
459 mono_blob_entry_equal (const char *str1, const char *str2) {
463 len = mono_metadata_decode_blob_size (str1, &end1);
464 len2 = mono_metadata_decode_blob_size (str2, &end2);
467 return memcmp (end1, end2, len) == 0;
471 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
475 gpointer oldkey, oldval;
477 copy = g_malloc (s1+s2);
478 memcpy (copy, b1, s1);
479 memcpy (copy + s1, b2, s2);
480 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
482 idx = GPOINTER_TO_UINT (oldval);
484 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
485 mono_image_add_stream_data (&assembly->blob, b2, s2);
486 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
492 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
496 guint32 size = buf->p - buf->buf;
498 g_assert (size <= (buf->end - buf->buf));
499 mono_metadata_encode_value (size, b, &b);
500 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
505 * dest may be misaligned.
508 swap_with_size (char *dest, const char* val, int len, int nelem) {
509 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
512 for (elem = 0; elem < nelem; ++elem) {
538 g_assert_not_reached ();
544 memcpy (dest, val, len * nelem);
549 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
553 guint32 idx = 0, len;
555 len = str->length * 2;
556 mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
559 char *swapped = g_malloc (2 * mono_string_length (str));
560 const char *p = (const char*)mono_string_chars (str);
562 swap_with_size (swapped, p, 2, mono_string_length (str));
563 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
572 #ifndef DISABLE_REFLECTION_EMIT
574 default_class_from_mono_type (MonoType *type)
576 switch (type->type) {
577 case MONO_TYPE_OBJECT:
578 return mono_defaults.object_class;
580 return mono_defaults.void_class;
581 case MONO_TYPE_BOOLEAN:
582 return mono_defaults.boolean_class;
584 return mono_defaults.char_class;
586 return mono_defaults.sbyte_class;
588 return mono_defaults.byte_class;
590 return mono_defaults.int16_class;
592 return mono_defaults.uint16_class;
594 return mono_defaults.int32_class;
596 return mono_defaults.uint32_class;
598 return mono_defaults.int_class;
600 return mono_defaults.uint_class;
602 return mono_defaults.int64_class;
604 return mono_defaults.uint64_class;
606 return mono_defaults.single_class;
608 return mono_defaults.double_class;
609 case MONO_TYPE_STRING:
610 return mono_defaults.string_class;
612 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
613 g_assert_not_reached ();
621 * mono_class_get_ref_info:
623 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
626 mono_class_get_ref_info (MonoClass *klass)
628 if (klass->ref_info_handle == 0)
631 return mono_gchandle_get_target (klass->ref_info_handle);
635 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
637 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
638 g_assert (klass->ref_info_handle != 0);
642 mono_class_free_ref_info (MonoClass *klass)
644 if (klass->ref_info_handle) {
645 mono_gchandle_free (klass->ref_info_handle);
646 klass->ref_info_handle = 0;
651 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
654 MonoGenericInst *class_inst;
659 class_inst = gclass->context.class_inst;
661 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
662 klass = gclass->container_class;
663 sigbuffer_add_value (buf, klass->byval_arg.type);
664 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
666 sigbuffer_add_value (buf, class_inst->type_argc);
667 for (i = 0; i < class_inst->type_argc; ++i)
668 encode_type (assembly, class_inst->type_argv [i], buf);
673 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
676 g_assert_not_reached ();
681 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
685 case MONO_TYPE_BOOLEAN:
699 case MONO_TYPE_STRING:
700 case MONO_TYPE_OBJECT:
701 case MONO_TYPE_TYPEDBYREF:
702 sigbuffer_add_value (buf, type->type);
705 sigbuffer_add_value (buf, type->type);
706 encode_type (assembly, type->data.type, buf);
708 case MONO_TYPE_SZARRAY:
709 sigbuffer_add_value (buf, type->type);
710 encode_type (assembly, &type->data.klass->byval_arg, buf);
712 case MONO_TYPE_VALUETYPE:
713 case MONO_TYPE_CLASS: {
714 MonoClass *k = mono_class_from_mono_type (type);
716 if (k->generic_container) {
717 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
718 encode_generic_class (assembly, gclass, buf);
721 * Make sure we use the correct type.
723 sigbuffer_add_value (buf, k->byval_arg.type);
725 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
726 * otherwise two typerefs could point to the same type, leading to
727 * verification errors.
729 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
733 case MONO_TYPE_ARRAY:
734 sigbuffer_add_value (buf, type->type);
735 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
736 sigbuffer_add_value (buf, type->data.array->rank);
737 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
738 sigbuffer_add_value (buf, 0);
740 case MONO_TYPE_GENERICINST:
741 encode_generic_class (assembly, type->data.generic_class, buf);
745 sigbuffer_add_value (buf, type->type);
746 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
749 g_error ("need to encode type %x", type->type);
754 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
757 sigbuffer_add_value (buf, MONO_TYPE_VOID);
761 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
765 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
770 for (i = 0; i < mono_array_length (modreq); ++i) {
771 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
772 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
773 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
777 for (i = 0; i < mono_array_length (modopt); ++i) {
778 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
779 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
780 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
785 #ifndef DISABLE_REFLECTION_EMIT
787 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
791 guint32 nparams = sig->param_count;
797 sigbuffer_init (&buf, 32);
799 * FIXME: vararg, explicit_this, differenc call_conv values...
801 idx = sig->call_convention;
803 idx |= 0x20; /* hasthis */
804 if (sig->generic_param_count)
805 idx |= 0x10; /* generic */
806 sigbuffer_add_byte (&buf, idx);
807 if (sig->generic_param_count)
808 sigbuffer_add_value (&buf, sig->generic_param_count);
809 sigbuffer_add_value (&buf, nparams);
810 encode_type (assembly, sig->ret, &buf);
811 for (i = 0; i < nparams; ++i) {
812 if (i == sig->sentinelpos)
813 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814 encode_type (assembly, sig->params [i], &buf);
816 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
817 sigbuffer_free (&buf);
823 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
826 * FIXME: reuse code from method_encode_signature().
830 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
831 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
832 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
835 sigbuffer_init (&buf, 32);
836 /* LAMESPEC: all the call conv spec is foobared */
837 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
838 if (mb->call_conv & 2)
839 idx |= 0x5; /* vararg */
840 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
841 idx |= 0x20; /* hasthis */
843 idx |= 0x10; /* generic */
844 sigbuffer_add_byte (&buf, idx);
846 sigbuffer_add_value (&buf, ngparams);
847 sigbuffer_add_value (&buf, nparams + notypes);
848 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
849 encode_reflection_type (assembly, mb->rtype, &buf);
850 for (i = 0; i < nparams; ++i) {
851 MonoArray *modreq = NULL;
852 MonoArray *modopt = NULL;
853 MonoReflectionType *pt;
855 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
856 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
857 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
858 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
859 encode_custom_modifiers (assembly, modreq, modopt, &buf);
860 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
861 encode_reflection_type (assembly, pt, &buf);
864 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
865 for (i = 0; i < notypes; ++i) {
866 MonoReflectionType *pt;
868 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
869 encode_reflection_type (assembly, pt, &buf);
872 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
873 sigbuffer_free (&buf);
878 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
880 MonoDynamicTable *table;
882 guint32 idx, sig_idx;
883 guint nl = mono_array_length (ilgen->locals);
887 sigbuffer_init (&buf, 32);
888 sigbuffer_add_value (&buf, 0x07);
889 sigbuffer_add_value (&buf, nl);
890 for (i = 0; i < nl; ++i) {
891 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
894 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
896 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
898 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
899 sigbuffer_free (&buf);
901 if (assembly->standalonesig_cache == NULL)
902 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
903 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
907 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
908 idx = table->next_idx ++;
910 alloc_table (table, table->rows);
911 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
913 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
915 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
921 method_count_clauses (MonoReflectionILGen *ilgen)
923 guint32 num_clauses = 0;
926 MonoILExceptionInfo *ex_info;
927 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
928 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
929 if (ex_info->handlers)
930 num_clauses += mono_array_length (ex_info->handlers);
938 #ifndef DISABLE_REFLECTION_EMIT
939 static MonoExceptionClause*
940 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
942 MonoExceptionClause *clauses;
943 MonoExceptionClause *clause;
944 MonoILExceptionInfo *ex_info;
945 MonoILExceptionBlock *ex_block;
946 guint32 finally_start;
947 int i, j, clause_index;;
949 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
952 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
953 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
954 finally_start = ex_info->start + ex_info->len;
955 if (!ex_info->handlers)
957 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
958 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
959 clause = &(clauses [clause_index]);
961 clause->flags = ex_block->type;
962 clause->try_offset = ex_info->start;
964 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
965 clause->try_len = finally_start - ex_info->start;
967 clause->try_len = ex_info->len;
968 clause->handler_offset = ex_block->start;
969 clause->handler_len = ex_block->len;
970 if (ex_block->extype) {
971 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
973 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
974 clause->data.filter_offset = ex_block->filter_offset;
976 clause->data.filter_offset = 0;
978 finally_start = ex_block->start + ex_block->len;
986 #endif /* !DISABLE_REFLECTION_EMIT */
989 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
995 gint32 num_locals = 0;
996 gint32 num_exception = 0;
999 char fat_header [12];
1001 guint16 short_value;
1002 guint32 local_sig = 0;
1003 guint32 header_size = 12;
1006 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1007 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1011 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1013 code = mb->ilgen->code;
1014 code_size = mb->ilgen->code_len;
1015 max_stack = mb->ilgen->max_stack;
1016 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1017 if (mb->ilgen->ex_handlers)
1018 num_exception = method_count_clauses (mb->ilgen);
1022 char *name = mono_string_to_utf8 (mb->name);
1023 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1024 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1027 mono_raise_exception (exception);
1030 code_size = mono_array_length (code);
1031 max_stack = 8; /* we probably need to run a verifier on the code... */
1034 stream_data_align (&assembly->code);
1036 /* check for exceptions, maxstack, locals */
1037 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1039 if (code_size < 64 && !(code_size & 1)) {
1040 flags = (code_size << 2) | 0x2;
1041 } else if (code_size < 32 && (code_size & 1)) {
1042 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1046 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1047 /* add to the fixup todo list */
1048 if (mb->ilgen && mb->ilgen->num_token_fixups)
1049 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1050 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1051 return assembly->text_rva + idx;
1055 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1057 * FIXME: need to set also the header size in fat_flags.
1058 * (and more sects and init locals flags)
1062 fat_flags |= METHOD_HEADER_MORE_SECTS;
1063 if (mb->init_locals)
1064 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1065 fat_header [0] = fat_flags;
1066 fat_header [1] = (header_size / 4 ) << 4;
1067 short_value = GUINT16_TO_LE (max_stack);
1068 memcpy (fat_header + 2, &short_value, 2);
1069 int_value = GUINT32_TO_LE (code_size);
1070 memcpy (fat_header + 4, &int_value, 4);
1071 int_value = GUINT32_TO_LE (local_sig);
1072 memcpy (fat_header + 8, &int_value, 4);
1073 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1074 /* add to the fixup todo list */
1075 if (mb->ilgen && mb->ilgen->num_token_fixups)
1076 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1078 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1079 if (num_exception) {
1080 unsigned char sheader [4];
1081 MonoILExceptionInfo * ex_info;
1082 MonoILExceptionBlock * ex_block;
1085 stream_data_align (&assembly->code);
1086 /* always use fat format for now */
1087 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1088 num_exception *= 6 * sizeof (guint32);
1089 num_exception += 4; /* include the size of the header */
1090 sheader [1] = num_exception & 0xff;
1091 sheader [2] = (num_exception >> 8) & 0xff;
1092 sheader [3] = (num_exception >> 16) & 0xff;
1093 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1094 /* fat header, so we are already aligned */
1096 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1097 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1098 if (ex_info->handlers) {
1099 int finally_start = ex_info->start + ex_info->len;
1100 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1102 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1104 val = GUINT32_TO_LE (ex_block->type);
1105 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1107 val = GUINT32_TO_LE (ex_info->start);
1108 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109 /* need fault, too, probably */
1110 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1111 val = GUINT32_TO_LE (finally_start - ex_info->start);
1113 val = GUINT32_TO_LE (ex_info->len);
1114 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1115 /* handler offset */
1116 val = GUINT32_TO_LE (ex_block->start);
1117 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1119 val = GUINT32_TO_LE (ex_block->len);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121 finally_start = ex_block->start + ex_block->len;
1122 if (ex_block->extype) {
1123 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1125 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1126 val = ex_block->filter_offset;
1130 val = GUINT32_TO_LE (val);
1131 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1132 /*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",
1133 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);*/
1136 g_error ("No clauses for ex info block %d", i);
1140 return assembly->text_rva + idx;
1144 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1147 MonoDynamicTable *table;
1150 table = &assembly->tables [table_idx];
1152 g_assert (col < table->columns);
1154 values = table->values + table->columns;
1155 for (i = 1; i <= table->rows; ++i) {
1156 if (values [col] == token)
1158 values += table->columns;
1164 * LOCKING: Acquires the loader lock.
1166 static MonoCustomAttrInfo*
1167 lookup_custom_attr (MonoImage *image, gpointer member)
1169 MonoCustomAttrInfo* res;
1171 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1176 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1180 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1182 /* FIXME: Need to do more checks */
1183 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1184 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1186 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1193 static MonoCustomAttrInfo*
1194 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1196 int i, index, count, not_visible;
1197 MonoCustomAttrInfo *ainfo;
1198 MonoReflectionCustomAttr *cattr;
1202 /* FIXME: check in assembly the Run flag is set */
1204 count = mono_array_length (cattrs);
1206 /* Skip nonpublic attributes since MS.NET seems to do the same */
1207 /* FIXME: This needs to be done more globally */
1209 for (i = 0; i < count; ++i) {
1210 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211 if (!custom_attr_visible (image, cattr))
1214 count -= not_visible;
1216 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1218 ainfo->image = image;
1219 ainfo->num_attrs = count;
1220 ainfo->cached = alloc_img != NULL;
1222 for (i = 0; i < count; ++i) {
1223 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1224 if (custom_attr_visible (image, cattr)) {
1225 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1226 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1227 ainfo->attrs [index].ctor = cattr->ctor->method;
1228 ainfo->attrs [index].data = saved;
1229 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1237 #ifndef DISABLE_REFLECTION_EMIT
1239 * LOCKING: Acquires the loader lock.
1242 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1244 MonoCustomAttrInfo *ainfo, *tmp;
1246 if (!cattrs || !mono_array_length (cattrs))
1249 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1251 mono_loader_lock ();
1252 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1254 mono_custom_attrs_free (tmp);
1255 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1256 mono_loader_unlock ();
1262 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1269 * idx is the table index of the object
1270 * type is one of MONO_CUSTOM_ATTR_*
1273 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1275 MonoDynamicTable *table;
1276 MonoReflectionCustomAttr *cattr;
1278 guint32 count, i, token;
1280 char *p = blob_size;
1282 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1285 count = mono_array_length (cattrs);
1286 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1287 table->rows += count;
1288 alloc_table (table, table->rows);
1289 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1290 idx <<= MONO_CUSTOM_ATTR_BITS;
1292 for (i = 0; i < count; ++i) {
1293 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1294 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1295 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1296 type = mono_metadata_token_index (token);
1297 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1298 switch (mono_metadata_token_table (token)) {
1299 case MONO_TABLE_METHOD:
1300 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1302 case MONO_TABLE_MEMBERREF:
1303 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1306 g_warning ("got wrong token in custom attr");
1309 values [MONO_CUSTOM_ATTR_TYPE] = type;
1311 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1312 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1313 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1314 values += MONO_CUSTOM_ATTR_SIZE;
1320 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1322 MonoDynamicTable *table;
1324 guint32 count, i, idx;
1325 MonoReflectionPermissionSet *perm;
1330 count = mono_array_length (permissions);
1331 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1332 table->rows += count;
1333 alloc_table (table, table->rows);
1335 for (i = 0; i < mono_array_length (permissions); ++i) {
1336 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1338 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1340 idx = mono_metadata_token_index (parent_token);
1341 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1342 switch (mono_metadata_token_table (parent_token)) {
1343 case MONO_TABLE_TYPEDEF:
1344 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1346 case MONO_TABLE_METHOD:
1347 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1349 case MONO_TABLE_ASSEMBLY:
1350 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1353 g_assert_not_reached ();
1356 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1357 values [MONO_DECL_SECURITY_PARENT] = idx;
1358 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1365 * Fill in the MethodDef and ParamDef tables for a method.
1366 * This is used for both normal methods and constructors.
1369 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1371 MonoDynamicTable *table;
1375 /* room in this table is already allocated */
1376 table = &assembly->tables [MONO_TABLE_METHOD];
1377 *mb->table_idx = table->next_idx ++;
1378 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1379 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1380 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1381 values [MONO_METHOD_FLAGS] = mb->attrs;
1382 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1383 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1384 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1386 table = &assembly->tables [MONO_TABLE_PARAM];
1387 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1389 mono_image_add_decl_security (assembly,
1390 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1393 MonoDynamicTable *mtable;
1396 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1397 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1400 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1401 if (mono_array_get (mb->pinfo, gpointer, i))
1404 table->rows += count;
1405 alloc_table (table, table->rows);
1406 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1407 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1408 MonoReflectionParamBuilder *pb;
1409 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1410 values [MONO_PARAM_FLAGS] = pb->attrs;
1411 values [MONO_PARAM_SEQUENCE] = i;
1412 if (pb->name != NULL) {
1413 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1415 values [MONO_PARAM_NAME] = 0;
1417 values += MONO_PARAM_SIZE;
1418 if (pb->marshal_info) {
1420 alloc_table (mtable, mtable->rows);
1421 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1422 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1423 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1425 pb->table_idx = table->next_idx++;
1426 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1427 guint32 field_type = 0;
1428 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1430 alloc_table (mtable, mtable->rows);
1431 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1432 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1433 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1434 mvalues [MONO_CONSTANT_TYPE] = field_type;
1435 mvalues [MONO_CONSTANT_PADDING] = 0;
1442 #ifndef DISABLE_REFLECTION_EMIT
1444 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1446 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1448 rmb->ilgen = mb->ilgen;
1449 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1450 rmb->parameters = mb->parameters;
1451 rmb->generic_params = mb->generic_params;
1452 rmb->generic_container = mb->generic_container;
1453 rmb->opt_types = NULL;
1454 rmb->pinfo = mb->pinfo;
1455 rmb->attrs = mb->attrs;
1456 rmb->iattrs = mb->iattrs;
1457 rmb->call_conv = mb->call_conv;
1458 rmb->code = mb->code;
1459 rmb->type = mb->type;
1460 rmb->name = mb->name;
1461 rmb->table_idx = &mb->table_idx;
1462 rmb->init_locals = mb->init_locals;
1463 rmb->skip_visibility = FALSE;
1464 rmb->return_modreq = mb->return_modreq;
1465 rmb->return_modopt = mb->return_modopt;
1466 rmb->param_modreq = mb->param_modreq;
1467 rmb->param_modopt = mb->param_modopt;
1468 rmb->permissions = mb->permissions;
1469 rmb->mhandle = mb->mhandle;
1474 rmb->charset = mb->charset;
1475 rmb->extra_flags = mb->extra_flags;
1476 rmb->native_cc = mb->native_cc;
1477 rmb->dllentry = mb->dllentry;
1483 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1485 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1487 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1489 rmb->ilgen = mb->ilgen;
1490 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1491 rmb->parameters = mb->parameters;
1492 rmb->generic_params = NULL;
1493 rmb->generic_container = NULL;
1494 rmb->opt_types = NULL;
1495 rmb->pinfo = mb->pinfo;
1496 rmb->attrs = mb->attrs;
1497 rmb->iattrs = mb->iattrs;
1498 rmb->call_conv = mb->call_conv;
1500 rmb->type = mb->type;
1501 rmb->name = mono_string_new (mono_domain_get (), name);
1502 rmb->table_idx = &mb->table_idx;
1503 rmb->init_locals = mb->init_locals;
1504 rmb->skip_visibility = FALSE;
1505 rmb->return_modreq = NULL;
1506 rmb->return_modopt = NULL;
1507 rmb->param_modreq = mb->param_modreq;
1508 rmb->param_modopt = mb->param_modopt;
1509 rmb->permissions = mb->permissions;
1510 rmb->mhandle = mb->mhandle;
1516 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1518 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1520 rmb->ilgen = mb->ilgen;
1521 rmb->rtype = mb->rtype;
1522 rmb->parameters = mb->parameters;
1523 rmb->generic_params = NULL;
1524 rmb->generic_container = NULL;
1525 rmb->opt_types = NULL;
1527 rmb->attrs = mb->attrs;
1529 rmb->call_conv = mb->call_conv;
1531 rmb->type = (MonoObject *) mb->owner;
1532 rmb->name = mb->name;
1533 rmb->table_idx = NULL;
1534 rmb->init_locals = mb->init_locals;
1535 rmb->skip_visibility = mb->skip_visibility;
1536 rmb->return_modreq = NULL;
1537 rmb->return_modopt = NULL;
1538 rmb->param_modreq = NULL;
1539 rmb->param_modopt = NULL;
1540 rmb->permissions = NULL;
1541 rmb->mhandle = mb->mhandle;
1548 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1550 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1551 MonoDynamicTable *table;
1555 if (!mb->override_method)
1558 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1560 alloc_table (table, table->rows);
1561 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1562 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1563 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1565 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1566 switch (mono_metadata_token_table (tok)) {
1567 case MONO_TABLE_MEMBERREF:
1568 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1570 case MONO_TABLE_METHOD:
1571 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1574 g_assert_not_reached ();
1576 values [MONO_METHODIMPL_DECLARATION] = tok;
1579 #ifndef DISABLE_REFLECTION_EMIT
1581 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1583 MonoDynamicTable *table;
1585 ReflectionMethodBuilder rmb;
1588 reflection_methodbuilder_from_method_builder (&rmb, mb);
1590 mono_image_basic_method (&rmb, assembly);
1591 mb->table_idx = *rmb.table_idx;
1593 if (mb->dll) { /* It's a P/Invoke method */
1595 /* map CharSet values to on-disk values */
1596 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1597 int extra_flags = mb->extra_flags;
1598 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1600 alloc_table (table, table->rows);
1601 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1603 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1604 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1606 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1608 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1610 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1611 table = &assembly->tables [MONO_TABLE_MODULEREF];
1613 alloc_table (table, table->rows);
1614 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1615 values [MONO_IMPLMAP_SCOPE] = table->rows;
1619 if (mb->generic_params) {
1620 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1621 table->rows += mono_array_length (mb->generic_params);
1622 alloc_table (table, table->rows);
1623 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1624 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1626 mono_image_get_generic_param_info (
1627 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1634 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1636 ReflectionMethodBuilder rmb;
1638 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1640 mono_image_basic_method (&rmb, assembly);
1641 mb->table_idx = *rmb.table_idx;
1646 type_get_fully_qualified_name (MonoType *type)
1648 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1652 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1656 klass = mono_class_from_mono_type (type);
1658 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659 ta = klass->image->assembly;
1660 if (ta->dynamic || (ta == ass)) {
1661 if (klass->generic_class || klass->generic_container)
1662 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1663 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1665 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1668 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1671 #ifndef DISABLE_REFLECTION_EMIT
1672 /*field_image is the image to which the eventual custom mods have been encoded against*/
1674 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1677 guint32 idx, i, token;
1679 if (!assembly->save)
1682 sigbuffer_init (&buf, 32);
1684 sigbuffer_add_value (&buf, 0x06);
1685 /* encode custom attributes before the type */
1686 if (type->num_mods) {
1687 for (i = 0; i < type->num_mods; ++i) {
1689 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1691 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1693 token = type->modifiers [i].token;
1696 if (type->modifiers [i].required)
1697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1699 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1701 sigbuffer_add_value (&buf, token);
1704 encode_type (assembly, type, &buf);
1705 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1706 sigbuffer_free (&buf);
1712 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1717 sigbuffer_init (&buf, 32);
1719 sigbuffer_add_value (&buf, 0x06);
1720 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721 /* encode custom attributes before the type */
1722 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1723 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724 sigbuffer_free (&buf);
1729 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1730 char blob_size [64];
1731 char *b = blob_size;
1734 guint32 idx = 0, len = 0, dummy = 0;
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737 guint32 fpa_double [2];
1742 p = buf = g_malloc (64);
1744 *ret_type = MONO_TYPE_CLASS;
1746 box_val = (char*)&dummy;
1748 box_val = ((char*)val) + sizeof (MonoObject);
1749 *ret_type = val->vtable->klass->byval_arg.type;
1752 switch (*ret_type) {
1753 case MONO_TYPE_BOOLEAN:
1758 case MONO_TYPE_CHAR:
1775 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776 fpa_p = (guint32*)box_val;
1777 fpa_double [0] = fpa_p [1];
1778 fpa_double [1] = fpa_p [0];
1779 box_val = (char*)fpa_double;
1783 case MONO_TYPE_VALUETYPE: {
1784 MonoClass *klass = val->vtable->klass;
1786 if (klass->enumtype) {
1787 *ret_type = mono_class_enum_basetype (klass)->type;
1789 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1792 g_error ("we can't encode valuetypes, we should have never reached this line");
1795 case MONO_TYPE_CLASS:
1797 case MONO_TYPE_STRING: {
1798 MonoString *str = (MonoString*)val;
1799 /* there is no signature */
1800 len = str->length * 2;
1801 mono_metadata_encode_value (len, b, &b);
1802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1804 char *swapped = g_malloc (2 * mono_string_length (str));
1805 const char *p = (const char*)mono_string_chars (str);
1807 swap_with_size (swapped, p, 2, mono_string_length (str));
1808 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1812 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1818 case MONO_TYPE_GENERICINST:
1819 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1822 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1825 /* there is no signature */
1826 mono_metadata_encode_value (len, b, &b);
1827 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1828 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1829 swap_with_size (blob_size, box_val, len, 1);
1830 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1832 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1840 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1845 sigbuffer_init (&buf, 32);
1847 sigbuffer_add_value (&buf, minfo->type);
1849 switch (minfo->type) {
1850 case MONO_NATIVE_BYVALTSTR:
1851 case MONO_NATIVE_BYVALARRAY:
1852 sigbuffer_add_value (&buf, minfo->count);
1854 case MONO_NATIVE_LPARRAY:
1855 if (minfo->eltype || minfo->has_size) {
1856 sigbuffer_add_value (&buf, minfo->eltype);
1857 if (minfo->has_size) {
1858 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1859 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1861 /* LAMESPEC: ElemMult is undocumented */
1862 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1866 case MONO_NATIVE_SAFEARRAY:
1868 sigbuffer_add_value (&buf, minfo->eltype);
1870 case MONO_NATIVE_CUSTOM:
1872 str = mono_string_to_utf8 (minfo->guid);
1874 sigbuffer_add_value (&buf, len);
1875 sigbuffer_add_mem (&buf, str, len);
1878 sigbuffer_add_value (&buf, 0);
1880 /* native type name */
1881 sigbuffer_add_value (&buf, 0);
1882 /* custom marshaler type name */
1883 if (minfo->marshaltype || minfo->marshaltyperef) {
1884 if (minfo->marshaltyperef)
1885 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1887 str = mono_string_to_utf8 (minfo->marshaltype);
1889 sigbuffer_add_value (&buf, len);
1890 sigbuffer_add_mem (&buf, str, len);
1893 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1894 sigbuffer_add_value (&buf, 0);
1896 if (minfo->mcookie) {
1897 str = mono_string_to_utf8 (minfo->mcookie);
1899 sigbuffer_add_value (&buf, len);
1900 sigbuffer_add_mem (&buf, str, len);
1903 sigbuffer_add_value (&buf, 0);
1909 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1910 sigbuffer_free (&buf);
1915 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1917 MonoDynamicTable *table;
1920 /* maybe this fixup should be done in the C# code */
1921 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1922 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1923 table = &assembly->tables [MONO_TABLE_FIELD];
1924 fb->table_idx = table->next_idx ++;
1925 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1926 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1927 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1928 values [MONO_FIELD_FLAGS] = fb->attrs;
1929 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1931 if (fb->offset != -1) {
1932 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1934 alloc_table (table, table->rows);
1935 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1936 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1937 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1939 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1940 guint32 field_type = 0;
1941 table = &assembly->tables [MONO_TABLE_CONSTANT];
1943 alloc_table (table, table->rows);
1944 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1945 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1946 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1947 values [MONO_CONSTANT_TYPE] = field_type;
1948 values [MONO_CONSTANT_PADDING] = 0;
1950 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1952 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1954 alloc_table (table, table->rows);
1955 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1956 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1958 * We store it in the code section because it's simpler for now.
1961 if (mono_array_length (fb->rva_data) >= 10)
1962 stream_data_align (&assembly->code);
1963 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1965 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1966 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1968 if (fb->marshal_info) {
1969 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1971 alloc_table (table, table->rows);
1972 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1973 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1974 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1979 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1982 guint32 nparams = 0;
1983 MonoReflectionMethodBuilder *mb = fb->get_method;
1984 MonoReflectionMethodBuilder *smb = fb->set_method;
1987 if (mb && mb->parameters)
1988 nparams = mono_array_length (mb->parameters);
1989 if (!mb && smb && smb->parameters)
1990 nparams = mono_array_length (smb->parameters) - 1;
1991 sigbuffer_init (&buf, 32);
1992 if (fb->call_conv & 0x20)
1993 sigbuffer_add_byte (&buf, 0x28);
1995 sigbuffer_add_byte (&buf, 0x08);
1996 sigbuffer_add_value (&buf, nparams);
1998 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1999 for (i = 0; i < nparams; ++i) {
2000 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2001 encode_reflection_type (assembly, pt, &buf);
2003 } else if (smb && smb->parameters) {
2004 /* the property type is the last param */
2005 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2006 for (i = 0; i < nparams; ++i) {
2007 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2008 encode_reflection_type (assembly, pt, &buf);
2011 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2014 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2015 sigbuffer_free (&buf);
2020 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2022 MonoDynamicTable *table;
2024 guint num_methods = 0;
2028 * we need to set things in the following tables:
2029 * PROPERTYMAP (info already filled in _get_type_info ())
2030 * PROPERTY (rows already preallocated in _get_type_info ())
2031 * METHOD (method info already done with the generic method code)
2035 table = &assembly->tables [MONO_TABLE_PROPERTY];
2036 pb->table_idx = table->next_idx ++;
2037 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2038 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2039 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2040 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2042 /* FIXME: we still don't handle 'other' methods */
2043 if (pb->get_method) num_methods ++;
2044 if (pb->set_method) num_methods ++;
2046 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2047 table->rows += num_methods;
2048 alloc_table (table, table->rows);
2050 if (pb->get_method) {
2051 semaidx = table->next_idx ++;
2052 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2053 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2054 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2055 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2057 if (pb->set_method) {
2058 semaidx = table->next_idx ++;
2059 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2061 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2062 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2064 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2065 guint32 field_type = 0;
2066 table = &assembly->tables [MONO_TABLE_CONSTANT];
2068 alloc_table (table, table->rows);
2069 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2070 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2071 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2072 values [MONO_CONSTANT_TYPE] = field_type;
2073 values [MONO_CONSTANT_PADDING] = 0;
2078 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2080 MonoDynamicTable *table;
2082 guint num_methods = 0;
2086 * we need to set things in the following tables:
2087 * EVENTMAP (info already filled in _get_type_info ())
2088 * EVENT (rows already preallocated in _get_type_info ())
2089 * METHOD (method info already done with the generic method code)
2092 table = &assembly->tables [MONO_TABLE_EVENT];
2093 eb->table_idx = table->next_idx ++;
2094 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2095 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2096 values [MONO_EVENT_FLAGS] = eb->attrs;
2097 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2100 * FIXME: we still don't handle 'other' methods
2102 if (eb->add_method) num_methods ++;
2103 if (eb->remove_method) num_methods ++;
2104 if (eb->raise_method) num_methods ++;
2106 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2107 table->rows += num_methods;
2108 alloc_table (table, table->rows);
2110 if (eb->add_method) {
2111 semaidx = table->next_idx ++;
2112 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2113 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2114 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2115 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2117 if (eb->remove_method) {
2118 semaidx = table->next_idx ++;
2119 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2121 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2122 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2124 if (eb->raise_method) {
2125 semaidx = table->next_idx ++;
2126 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2128 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2129 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2134 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2136 MonoDynamicTable *table;
2137 guint32 num_constraints, i;
2141 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2142 num_constraints = gparam->iface_constraints ?
2143 mono_array_length (gparam->iface_constraints) : 0;
2144 table->rows += num_constraints;
2145 if (gparam->base_type)
2147 alloc_table (table, table->rows);
2149 if (gparam->base_type) {
2150 table_idx = table->next_idx ++;
2151 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2153 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2154 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2155 assembly, mono_reflection_type_get_handle (gparam->base_type));
2158 for (i = 0; i < num_constraints; i++) {
2159 MonoReflectionType *constraint = mono_array_get (
2160 gparam->iface_constraints, gpointer, i);
2162 table_idx = table->next_idx ++;
2163 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2165 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2166 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2167 assembly, mono_reflection_type_get_handle (constraint));
2172 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2174 GenericParamTableEntry *entry;
2177 * The GenericParam table must be sorted according to the `owner' field.
2178 * We need to do this sorting prior to writing the GenericParamConstraint
2179 * table, since we have to use the final GenericParam table indices there
2180 * and they must also be sorted.
2183 entry = g_new0 (GenericParamTableEntry, 1);
2184 entry->owner = owner;
2185 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2186 MOVING_GC_REGISTER (&entry->gparam);
2187 entry->gparam = gparam;
2189 g_ptr_array_add (assembly->gen_params, entry);
2193 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2195 MonoDynamicTable *table;
2196 MonoGenericParam *param;
2200 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2201 table_idx = table->next_idx ++;
2202 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2204 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2206 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2207 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2208 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2209 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2211 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2213 encode_constraints (entry->gparam, table_idx, assembly);
2217 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2219 MonoDynamicTable *table;
2222 guint32 cols [MONO_ASSEMBLY_SIZE];
2226 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2229 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2230 table = &assembly->tables [MONO_TABLE_MODULEREF];
2231 token = table->next_idx ++;
2233 alloc_table (table, table->rows);
2234 values = table->values + token * MONO_MODULEREF_SIZE;
2235 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2237 token <<= MONO_RESOLTION_SCOPE_BITS;
2238 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2239 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2244 if (image->assembly->dynamic)
2246 memset (cols, 0, sizeof (cols));
2248 /* image->assembly->image is the manifest module */
2249 image = image->assembly->image;
2250 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2253 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2254 token = table->next_idx ++;
2256 alloc_table (table, table->rows);
2257 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2258 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2259 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2260 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2261 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2262 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2263 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2264 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2265 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2267 if (strcmp ("", image->assembly->aname.culture)) {
2268 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2269 image->assembly->aname.culture);
2272 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2273 guchar pubtoken [9];
2275 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2276 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2278 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2280 token <<= MONO_RESOLTION_SCOPE_BITS;
2281 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2282 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2287 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2289 MonoDynamicTable *table;
2294 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2297 sigbuffer_init (&buf, 32);
2298 switch (type->type) {
2299 case MONO_TYPE_FNPTR:
2301 case MONO_TYPE_SZARRAY:
2302 case MONO_TYPE_ARRAY:
2304 case MONO_TYPE_MVAR:
2305 case MONO_TYPE_GENERICINST:
2306 encode_type (assembly, type, &buf);
2308 case MONO_TYPE_CLASS:
2309 case MONO_TYPE_VALUETYPE: {
2310 MonoClass *k = mono_class_from_mono_type (type);
2311 if (!k || !k->generic_container) {
2312 sigbuffer_free (&buf);
2315 encode_type (assembly, type, &buf);
2319 sigbuffer_free (&buf);
2323 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2324 if (assembly->save) {
2325 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2326 alloc_table (table, table->rows + 1);
2327 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2328 values [MONO_TYPESPEC_SIGNATURE] = token;
2330 sigbuffer_free (&buf);
2332 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2333 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2339 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2341 MonoDynamicTable *table;
2343 guint32 token, scope, enclosing;
2346 /* if the type requires a typespec, we must try that first*/
2347 if (try_typespec && (token = create_typespec (assembly, type)))
2349 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2352 klass = mono_class_from_mono_type (type);
2354 klass = mono_class_from_mono_type (type);
2357 * If it's in the same module and not a generic type parameter:
2359 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2360 (type->type != MONO_TYPE_MVAR)) {
2361 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2362 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2363 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2367 if (klass->nested_in) {
2368 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2369 /* get the typeref idx of the enclosing type */
2370 enclosing >>= MONO_TYPEDEFORREF_BITS;
2371 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2373 scope = resolution_scope_from_image (assembly, klass->image);
2375 table = &assembly->tables [MONO_TABLE_TYPEREF];
2376 if (assembly->save) {
2377 alloc_table (table, table->rows + 1);
2378 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2379 values [MONO_TYPEREF_SCOPE] = scope;
2380 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2381 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2383 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2384 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2386 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2391 * Despite the name, we handle also TypeSpec (with the above helper).
2394 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2396 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2399 #ifndef DISABLE_REFLECTION_EMIT
2401 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2403 MonoDynamicTable *table;
2405 guint32 token, pclass;
2407 switch (parent & MONO_TYPEDEFORREF_MASK) {
2408 case MONO_TYPEDEFORREF_TYPEREF:
2409 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2411 case MONO_TYPEDEFORREF_TYPESPEC:
2412 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2414 case MONO_TYPEDEFORREF_TYPEDEF:
2415 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2418 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2421 /* extract the index */
2422 parent >>= MONO_TYPEDEFORREF_BITS;
2424 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2426 if (assembly->save) {
2427 alloc_table (table, table->rows + 1);
2428 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2429 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2430 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2431 values [MONO_MEMBERREF_SIGNATURE] = sig;
2434 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2441 * Insert a memberef row into the metadata: the token that point to the memberref
2442 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2443 * mono_image_get_fieldref_token()).
2444 * The sig param is an index to an already built signature.
2447 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2449 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2450 return mono_image_add_memberef_row (assembly, parent, name, sig);
2455 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2458 MonoMethodSignature *sig;
2460 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2462 if (create_typespec) {
2463 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2468 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2469 if (token && !create_typespec)
2472 g_assert (!method->is_inflated);
2475 * A methodref signature can't contain an unmanaged calling convention.
2477 sig = mono_metadata_signature_dup (mono_method_signature (method));
2478 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2479 sig->call_convention = MONO_CALL_DEFAULT;
2480 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2481 method->name, method_encode_signature (assembly, sig));
2483 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2486 if (create_typespec) {
2487 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2488 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2489 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2491 if (assembly->save) {
2494 alloc_table (table, table->rows + 1);
2495 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2496 values [MONO_METHODSPEC_METHOD] = token;
2497 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2500 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2502 /*methodspec and memberef tokens are diferent, */
2503 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2510 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2512 guint32 token, parent, sig;
2513 ReflectionMethodBuilder rmb;
2515 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2517 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2521 name = mono_string_to_utf8 (method->name);
2522 reflection_methodbuilder_from_method_builder (&rmb, method);
2525 * A methodref signature can't contain an unmanaged calling convention.
2526 * Since some flags are encoded as part of call_conv, we need to check against it.
2528 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2529 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2531 sig = method_builder_encode_signature (assembly, &rmb);
2533 if (tb->generic_params)
2534 parent = create_generic_typespec (assembly, tb);
2536 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2538 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2541 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2546 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2547 const gchar *name, guint32 sig)
2549 MonoDynamicTable *table;
2553 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2555 if (assembly->save) {
2556 alloc_table (table, table->rows + 1);
2557 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2558 values [MONO_MEMBERREF_CLASS] = original;
2559 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2560 values [MONO_MEMBERREF_SIGNATURE] = sig;
2563 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2570 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2574 guint32 nparams = mono_array_length (mb->generic_params);
2577 if (!assembly->save)
2580 sigbuffer_init (&buf, 32);
2582 sigbuffer_add_value (&buf, 0xa);
2583 sigbuffer_add_value (&buf, nparams);
2585 for (i = 0; i < nparams; i++) {
2586 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2587 sigbuffer_add_value (&buf, i);
2590 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2591 sigbuffer_free (&buf);
2596 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2598 MonoDynamicTable *table;
2600 guint32 token, mtoken = 0;
2602 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2606 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2608 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2609 switch (mono_metadata_token_table (mtoken)) {
2610 case MONO_TABLE_MEMBERREF:
2611 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2613 case MONO_TABLE_METHOD:
2614 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2617 g_assert_not_reached ();
2620 if (assembly->save) {
2621 alloc_table (table, table->rows + 1);
2622 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2623 values [MONO_METHODSPEC_METHOD] = mtoken;
2624 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2627 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2630 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2635 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2639 if (mb->generic_params && create_methodspec)
2640 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2642 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2646 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2647 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2652 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2654 guint32 token, parent, sig;
2655 ReflectionMethodBuilder rmb;
2657 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2659 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2663 g_assert (tb->generic_params);
2665 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2667 parent = create_generic_typespec (assembly, tb);
2668 name = mono_string_to_utf8 (rmb.name);
2669 sig = method_builder_encode_signature (assembly, &rmb);
2671 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2674 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2680 is_field_on_inst (MonoClassField *field)
2682 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2686 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2689 get_field_on_inst_generic_type (MonoClassField *field)
2691 MonoClass *class, *gtd;
2692 MonoDynamicGenericClass *dgclass;
2695 g_assert (is_field_on_inst (field));
2697 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2699 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2700 field_index = field - dgclass->fields;
2701 return dgclass->field_generic_types [field_index];
2704 class = field->parent;
2705 gtd = class->generic_class->container_class;
2707 if (field >= class->fields && field - class->fields < class->field.count) {
2708 field_index = field - class->fields;
2709 return gtd->fields [field_index].type;
2712 g_assert_not_reached ();
2716 #ifndef DISABLE_REFLECTION_EMIT
2718 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2724 g_assert (field->parent);
2726 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2730 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2731 int index = field - field->parent->fields;
2732 type = field->parent->generic_class->container_class->fields [index].type;
2734 if (is_field_on_inst (field))
2735 type = get_field_on_inst_generic_type (field);
2739 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2740 mono_field_get_name (field),
2741 fieldref_encode_signature (assembly, field->parent->image, type));
2742 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2747 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2751 MonoGenericClass *gclass;
2752 MonoDynamicGenericClass *dgclass;
2756 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2759 if (is_sre_field_builder (mono_object_class (f->fb))) {
2760 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2761 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2762 klass = mono_class_from_mono_type (type);
2763 gclass = type->data.generic_class;
2764 g_assert (gclass->is_dynamic);
2765 dgclass = (MonoDynamicGenericClass *) gclass;
2767 name = mono_string_to_utf8 (fb->name);
2768 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2769 field_encode_signature (assembly, fb));
2771 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2773 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2775 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2776 klass = mono_class_from_mono_type (type);
2778 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2779 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2781 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2782 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2785 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2790 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2794 MonoGenericClass *gclass;
2797 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2799 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2803 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2804 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2805 MonoDynamicGenericClass *dgclass;
2806 ReflectionMethodBuilder rmb;
2809 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2810 klass = mono_class_from_mono_type (type);
2812 gclass = type->data.generic_class;
2813 g_assert (gclass->is_dynamic);
2814 dgclass = (MonoDynamicGenericClass *) gclass;
2816 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2818 name = mono_string_to_utf8 (rmb.name);
2820 sig = method_builder_encode_signature (assembly, &rmb);
2822 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2824 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2825 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2827 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2828 klass = mono_class_from_mono_type (type);
2830 sig = method_encode_signature (assembly, mono_method_signature (mm));
2831 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2833 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2834 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2838 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2843 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2846 MonoGenericContext tmp_context;
2847 MonoType **type_argv;
2848 MonoGenericInst *ginst;
2849 MonoMethod *method, *inflated;
2852 method = inflate_method (m->inst, (MonoObject*)m->mb);
2854 klass = method->klass;
2856 if (m->method_args == NULL)
2859 if (method->is_inflated)
2860 method = ((MonoMethodInflated *) method)->declaring;
2862 count = mono_array_length (m->method_args);
2864 type_argv = g_new0 (MonoType *, count);
2865 for (i = 0; i < count; i++) {
2866 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2867 type_argv [i] = mono_reflection_type_get_handle (garg);
2869 ginst = mono_metadata_get_generic_inst (count, type_argv);
2872 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2873 tmp_context.method_inst = ginst;
2875 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2880 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2882 guint32 sig, token = 0;
2886 if (m->method_args) {
2887 MonoMethod *inflated;
2889 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2890 if (create_methodspec)
2891 token = mono_image_get_methodspec_token (assembly, inflated);
2893 token = mono_image_get_inflated_method_token (assembly, inflated);
2897 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2901 if (is_sre_method_builder (mono_object_class (m->mb))) {
2902 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2903 MonoGenericClass *gclass;
2904 ReflectionMethodBuilder rmb;
2907 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2908 klass = mono_class_from_mono_type (type);
2909 gclass = type->data.generic_class;
2910 g_assert (gclass->is_dynamic);
2912 reflection_methodbuilder_from_method_builder (&rmb, mb);
2914 name = mono_string_to_utf8 (rmb.name);
2916 sig = method_builder_encode_signature (assembly, &rmb);
2918 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2920 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2921 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2923 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2924 klass = mono_class_from_mono_type (type);
2926 sig = method_encode_signature (assembly, mono_method_signature (mm));
2927 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2929 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2930 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2933 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2938 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2942 guint32 nparams = context->method_inst->type_argc;
2945 if (!assembly->save)
2948 sigbuffer_init (&buf, 32);
2950 * FIXME: vararg, explicit_this, differenc call_conv values...
2952 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2953 sigbuffer_add_value (&buf, nparams);
2955 for (i = 0; i < nparams; i++)
2956 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2958 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2959 sigbuffer_free (&buf);
2964 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2966 MonoDynamicTable *table;
2968 guint32 token, mtoken = 0, sig;
2969 MonoMethodInflated *imethod;
2970 MonoMethod *declaring;
2972 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2974 g_assert (method->is_inflated);
2975 imethod = (MonoMethodInflated *) method;
2976 declaring = imethod->declaring;
2978 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2979 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2981 if (!mono_method_signature (declaring)->generic_param_count)
2984 switch (mono_metadata_token_table (mtoken)) {
2985 case MONO_TABLE_MEMBERREF:
2986 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2988 case MONO_TABLE_METHOD:
2989 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2992 g_assert_not_reached ();
2995 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2997 if (assembly->save) {
2998 alloc_table (table, table->rows + 1);
2999 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3000 values [MONO_METHODSPEC_METHOD] = mtoken;
3001 values [MONO_METHODSPEC_SIGNATURE] = sig;
3004 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3011 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3013 MonoMethodInflated *imethod;
3016 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3020 g_assert (method->is_inflated);
3021 imethod = (MonoMethodInflated *) method;
3023 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3024 token = method_encode_methodspec (assembly, method);
3026 guint32 sig = method_encode_signature (
3027 assembly, mono_method_signature (imethod->declaring));
3028 token = mono_image_get_memberref_token (
3029 assembly, &method->klass->byval_arg, method->name, sig);
3032 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3037 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3039 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3042 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3043 token = mono_image_get_memberref_token (
3044 assembly, &m->klass->byval_arg, m->name, sig);
3050 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3052 MonoDynamicTable *table;
3061 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3062 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3063 * Because of this, we must not insert it into the `typeref' hash table.
3065 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3066 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3070 sigbuffer_init (&buf, 32);
3072 g_assert (tb->generic_params);
3073 klass = mono_class_from_mono_type (type);
3075 if (tb->generic_container)
3076 mono_reflection_create_generic_class (tb);
3078 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3079 g_assert (klass->generic_container);
3080 sigbuffer_add_value (&buf, klass->byval_arg.type);
3081 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3083 count = mono_array_length (tb->generic_params);
3084 sigbuffer_add_value (&buf, count);
3085 for (i = 0; i < count; i++) {
3086 MonoReflectionGenericParam *gparam;
3088 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3090 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3093 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3095 if (assembly->save) {
3096 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3097 alloc_table (table, table->rows + 1);
3098 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3099 values [MONO_TYPESPEC_SIGNATURE] = token;
3101 sigbuffer_free (&buf);
3103 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3104 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3110 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3113 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3115 int i, count, len, pos;
3120 count += mono_array_length (modreq);
3122 count += mono_array_length (modopt);
3125 return mono_metadata_type_dup (NULL, type);
3127 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3129 memcpy (t, type, MONO_SIZEOF_TYPE);
3131 t->num_mods = count;
3134 for (i = 0; i < mono_array_length (modreq); ++i) {
3135 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3136 t->modifiers [pos].required = 1;
3137 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3142 for (i = 0; i < mono_array_length (modopt); ++i) {
3143 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3144 t->modifiers [pos].required = 0;
3145 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3154 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3156 MonoDynamicTable *table;
3158 MonoType *custom = NULL;
3160 guint32 token, pclass, parent, sig;
3163 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3167 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3168 name = mono_string_to_utf8 (fb->name);
3170 /* fb->type does not include the custom modifiers */
3171 /* FIXME: We should do this in one place when a fieldbuilder is created */
3172 if (fb->modreq || fb->modopt) {
3173 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3174 sig = fieldref_encode_signature (assembly, NULL, custom);
3177 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3180 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3181 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3183 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3184 parent >>= MONO_TYPEDEFORREF_BITS;
3186 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3188 if (assembly->save) {
3189 alloc_table (table, table->rows + 1);
3190 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3191 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3192 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3193 values [MONO_MEMBERREF_SIGNATURE] = sig;
3196 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3198 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3204 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3211 if (!assembly->save)
3214 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3215 g_assert (helper->type == 2);
3217 if (helper->arguments)
3218 nargs = mono_array_length (helper->arguments);
3222 size = 10 + (nargs * 10);
3224 sigbuffer_init (&buf, 32);
3226 /* Encode calling convention */
3227 /* Change Any to Standard */
3228 if ((helper->call_conv & 0x03) == 0x03)
3229 helper->call_conv = 0x01;
3230 /* explicit_this implies has_this */
3231 if (helper->call_conv & 0x40)
3232 helper->call_conv &= 0x20;
3234 if (helper->call_conv == 0) { /* Unmanaged */
3235 idx = helper->unmanaged_call_conv - 1;
3238 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3239 if (helper->call_conv & 0x02) /* varargs */
3243 sigbuffer_add_byte (&buf, idx);
3244 sigbuffer_add_value (&buf, nargs);
3245 encode_reflection_type (assembly, helper->return_type, &buf);
3246 for (i = 0; i < nargs; ++i) {
3247 MonoArray *modreqs = NULL;
3248 MonoArray *modopts = NULL;
3249 MonoReflectionType *pt;
3251 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3252 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3253 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3254 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3256 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3257 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3258 encode_reflection_type (assembly, pt, &buf);
3260 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261 sigbuffer_free (&buf);
3267 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3270 MonoDynamicTable *table;
3273 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3274 idx = table->next_idx ++;
3276 alloc_table (table, table->rows);
3277 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3279 values [MONO_STAND_ALONE_SIGNATURE] =
3280 mono_reflection_encode_sighelper (assembly, helper);
3286 reflection_cc_to_file (int call_conv) {
3287 switch (call_conv & 0x3) {
3289 case 1: return MONO_CALL_DEFAULT;
3290 case 2: return MONO_CALL_VARARG;
3292 g_assert_not_reached ();
3296 #endif /* !DISABLE_REFLECTION_EMIT */
3300 MonoMethodSignature *sig;
3305 #ifndef DISABLE_REFLECTION_EMIT
3307 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3312 MonoMethodSignature *sig;
3316 name = mono_string_to_utf8 (m->name);
3317 nparams = mono_array_length (m->parameters);
3318 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3320 sig->sentinelpos = -1;
3321 sig->call_convention = reflection_cc_to_file (m->call_conv);
3322 sig->param_count = nparams;
3323 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3324 mtype = mono_reflection_type_get_handle (m->parent);
3325 for (i = 0; i < nparams; ++i)
3326 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3328 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3330 if (strcmp (name, am->name) == 0 &&
3331 mono_metadata_type_equal (am->parent, mtype) &&
3332 mono_metadata_signature_equal (am->sig, sig)) {
3335 m->table_idx = am->token & 0xffffff;
3339 am = g_new0 (ArrayMethod, 1);
3343 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3344 method_encode_signature (assembly, sig));
3345 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3346 m->table_idx = am->token & 0xffffff;
3351 * Insert into the metadata tables all the info about the TypeBuilder tb.
3352 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3355 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3357 MonoDynamicTable *table;
3359 int i, is_object = 0, is_system = 0;
3362 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3363 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3364 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3365 n = mono_string_to_utf8 (tb->name);
3366 if (strcmp (n, "Object") == 0)
3368 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3370 n = mono_string_to_utf8 (tb->nspace);
3371 if (strcmp (n, "System") == 0)
3373 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3375 if (tb->parent && !(is_system && is_object) &&
3376 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3377 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3379 values [MONO_TYPEDEF_EXTENDS] = 0;
3381 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3382 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3385 * if we have explicitlayout or sequentiallayouts, output data in the
3386 * ClassLayout table.
3388 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3389 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3390 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3392 alloc_table (table, table->rows);
3393 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3394 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3395 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3396 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3399 /* handle interfaces */
3400 if (tb->interfaces) {
3401 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3403 table->rows += mono_array_length (tb->interfaces);
3404 alloc_table (table, table->rows);
3405 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3406 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3407 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3408 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3409 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3410 values += MONO_INTERFACEIMPL_SIZE;
3416 table = &assembly->tables [MONO_TABLE_FIELD];
3417 table->rows += tb->num_fields;
3418 alloc_table (table, table->rows);
3419 for (i = 0; i < tb->num_fields; ++i)
3420 mono_image_get_field_info (
3421 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3424 /* handle constructors */
3426 table = &assembly->tables [MONO_TABLE_METHOD];
3427 table->rows += mono_array_length (tb->ctors);
3428 alloc_table (table, table->rows);
3429 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3430 mono_image_get_ctor_info (domain,
3431 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3434 /* handle methods */
3436 table = &assembly->tables [MONO_TABLE_METHOD];
3437 table->rows += tb->num_methods;
3438 alloc_table (table, table->rows);
3439 for (i = 0; i < tb->num_methods; ++i)
3440 mono_image_get_method_info (
3441 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3444 /* Do the same with properties etc.. */
3445 if (tb->events && mono_array_length (tb->events)) {
3446 table = &assembly->tables [MONO_TABLE_EVENT];
3447 table->rows += mono_array_length (tb->events);
3448 alloc_table (table, table->rows);
3449 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3451 alloc_table (table, table->rows);
3452 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3453 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3454 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3455 for (i = 0; i < mono_array_length (tb->events); ++i)
3456 mono_image_get_event_info (
3457 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3459 if (tb->properties && mono_array_length (tb->properties)) {
3460 table = &assembly->tables [MONO_TABLE_PROPERTY];
3461 table->rows += mono_array_length (tb->properties);
3462 alloc_table (table, table->rows);
3463 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3465 alloc_table (table, table->rows);
3466 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3467 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3468 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3469 for (i = 0; i < mono_array_length (tb->properties); ++i)
3470 mono_image_get_property_info (
3471 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3474 /* handle generic parameters */
3475 if (tb->generic_params) {
3476 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3477 table->rows += mono_array_length (tb->generic_params);
3478 alloc_table (table, table->rows);
3479 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3480 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3482 mono_image_get_generic_param_info (
3483 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3487 mono_image_add_decl_security (assembly,
3488 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3491 MonoDynamicTable *ntable;
3493 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3494 ntable->rows += mono_array_length (tb->subtypes);
3495 alloc_table (ntable, ntable->rows);
3496 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3498 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3499 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3501 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3502 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3503 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3504 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3505 mono_string_to_utf8 (tb->name), tb->table_idx,
3506 ntable->next_idx, ntable->rows);*/
3507 values += MONO_NESTED_CLASS_SIZE;
3515 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3519 mono_ptr_array_append (*types, type);
3521 if (!type->subtypes)
3524 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3525 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3526 collect_types (types, subtype);
3531 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3533 if ((*type1)->table_idx < (*type2)->table_idx)
3536 if ((*type1)->table_idx > (*type2)->table_idx)
3543 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3548 for (i = 0; i < mono_array_length (pinfo); ++i) {
3549 MonoReflectionParamBuilder *pb;
3550 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3553 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3558 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3561 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3563 for (i = 0; i < tb->num_fields; ++i) {
3564 MonoReflectionFieldBuilder* fb;
3565 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3566 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3570 for (i = 0; i < mono_array_length (tb->events); ++i) {
3571 MonoReflectionEventBuilder* eb;
3572 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3573 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3576 if (tb->properties) {
3577 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3578 MonoReflectionPropertyBuilder* pb;
3579 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3580 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3584 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3585 MonoReflectionCtorBuilder* cb;
3586 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3587 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3588 params_add_cattrs (assembly, cb->pinfo);
3593 for (i = 0; i < tb->num_methods; ++i) {
3594 MonoReflectionMethodBuilder* mb;
3595 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3596 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3597 params_add_cattrs (assembly, mb->pinfo);
3602 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3603 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3608 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3612 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3614 if (moduleb->global_methods) {
3615 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3616 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3617 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3618 params_add_cattrs (assembly, mb->pinfo);
3622 if (moduleb->global_fields) {
3623 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3624 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3625 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3629 if (moduleb->types) {
3630 for (i = 0; i < moduleb->num_types; ++i)
3631 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3636 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3638 MonoDynamicTable *table;
3642 char *b = blob_size;
3645 table = &assembly->tables [MONO_TABLE_FILE];
3647 alloc_table (table, table->rows);
3648 values = table->values + table->next_idx * MONO_FILE_SIZE;
3649 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3650 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3651 if (module->image->dynamic) {
3652 /* This depends on the fact that the main module is emitted last */
3653 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3654 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3657 path = g_strdup (module->image->name);
3659 mono_sha1_get_digest_from_file (path, hash);
3662 mono_metadata_encode_value (20, b, &b);
3663 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3664 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3669 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3671 MonoDynamicTable *table;
3674 table = &assembly->tables [MONO_TABLE_MODULE];
3675 mb->table_idx = table->next_idx ++;
3676 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3677 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3680 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3681 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3682 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3683 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3687 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3688 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3690 MonoDynamicTable *table;
3694 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3695 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3698 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3700 alloc_table (table, table->rows);
3701 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3703 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3704 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3705 if (klass->nested_in)
3706 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3708 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3709 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3710 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3712 res = table->next_idx;
3716 /* Emit nested types */
3717 if (klass->ext && klass->ext->nested_classes) {
3720 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3721 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3728 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3729 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3734 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3736 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3738 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3739 parent_index, assembly);
3743 * We need to do this ourselves since klass->nested_classes is not set up.
3746 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3747 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3752 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3753 guint32 module_index, MonoDynamicImage *assembly)
3755 MonoImage *image = module->image;
3759 t = &image->tables [MONO_TABLE_TYPEDEF];
3761 for (i = 0; i < t->rows; ++i) {
3762 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3764 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3765 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3770 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3772 MonoDynamicTable *table;
3774 guint32 scope, scope_idx, impl, current_idx;
3775 gboolean forwarder = TRUE;
3776 gpointer iter = NULL;
3779 if (klass->nested_in) {
3780 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3783 scope = resolution_scope_from_image (assembly, klass->image);
3784 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3785 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3786 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3789 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3792 alloc_table (table, table->rows);
3793 current_idx = table->next_idx;
3794 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3796 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3797 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3798 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3799 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3800 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3804 while ((nested = mono_class_get_nested_types (klass, &iter)))
3805 add_exported_type (assemblyb, assembly, nested, current_idx);
3809 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3814 if (!assemblyb->type_forwarders)
3817 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3818 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3823 type = mono_reflection_type_get_handle (t);
3826 klass = mono_class_from_mono_type (type);
3828 add_exported_type (assemblyb, assembly, klass, 0);
3832 #define align_pointer(base,p)\
3834 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3836 (p) += 4 - (__diff & 3);\
3840 compare_constants (const void *a, const void *b)
3842 const guint32 *a_values = a;
3843 const guint32 *b_values = b;
3844 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3848 compare_semantics (const void *a, const void *b)
3850 const guint32 *a_values = a;
3851 const guint32 *b_values = b;
3852 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3855 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3859 compare_custom_attrs (const void *a, const void *b)
3861 const guint32 *a_values = a;
3862 const guint32 *b_values = b;
3864 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3868 compare_field_marshal (const void *a, const void *b)
3870 const guint32 *a_values = a;
3871 const guint32 *b_values = b;
3873 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3877 compare_nested (const void *a, const void *b)
3879 const guint32 *a_values = a;
3880 const guint32 *b_values = b;
3882 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3886 compare_genericparam (const void *a, const void *b)
3888 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3889 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3891 if ((*b_entry)->owner == (*a_entry)->owner)
3893 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3894 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3896 return (*a_entry)->owner - (*b_entry)->owner;
3900 compare_declsecurity_attrs (const void *a, const void *b)
3902 const guint32 *a_values = a;
3903 const guint32 *b_values = b;
3905 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3909 compare_interface_impl (const void *a, const void *b)
3911 const guint32 *a_values = a;
3912 const guint32 *b_values = b;
3914 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3918 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3922 pad_heap (MonoDynamicStream *sh)
3924 if (sh->index & 3) {
3925 int sz = 4 - (sh->index & 3);
3926 memset (sh->data + sh->index, 0, sz);
3933 MonoDynamicStream *stream;
3937 * build_compressed_metadata() fills in the blob of data that represents the
3938 * raw metadata as it will be saved in the PE file. The five streams are output
3939 * and the metadata tables are comnpressed from the guint32 array representation,
3940 * to the compressed on-disk format.
3943 build_compressed_metadata (MonoDynamicImage *assembly)
3945 MonoDynamicTable *table;
3947 guint64 valid_mask = 0;
3948 guint64 sorted_mask;
3949 guint32 heapt_size = 0;
3950 guint32 meta_size = 256; /* allow for header and other stuff */
3951 guint32 table_offset;
3952 guint32 ntables = 0;
3958 struct StreamDesc stream_desc [5];
3960 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3961 for (i = 0; i < assembly->gen_params->len; i++){
3962 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3963 write_generic_param_entry (assembly, entry);
3966 stream_desc [0].name = "#~";
3967 stream_desc [0].stream = &assembly->tstream;
3968 stream_desc [1].name = "#Strings";
3969 stream_desc [1].stream = &assembly->sheap;
3970 stream_desc [2].name = "#US";
3971 stream_desc [2].stream = &assembly->us;
3972 stream_desc [3].name = "#Blob";
3973 stream_desc [3].stream = &assembly->blob;
3974 stream_desc [4].name = "#GUID";
3975 stream_desc [4].stream = &assembly->guid;
3977 /* tables that are sorted */
3978 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3979 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3980 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3981 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3982 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3983 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3984 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3986 /* Compute table sizes */
3987 /* the MonoImage has already been created in mono_image_basic_init() */
3988 meta = &assembly->image;
3990 /* sizes should be multiple of 4 */
3991 pad_heap (&assembly->blob);
3992 pad_heap (&assembly->guid);
3993 pad_heap (&assembly->sheap);
3994 pad_heap (&assembly->us);
3996 /* Setup the info used by compute_sizes () */
3997 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3998 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3999 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4001 meta_size += assembly->blob.index;
4002 meta_size += assembly->guid.index;
4003 meta_size += assembly->sheap.index;
4004 meta_size += assembly->us.index;
4006 for (i=0; i < MONO_TABLE_NUM; ++i)
4007 meta->tables [i].rows = assembly->tables [i].rows;
4009 for (i = 0; i < MONO_TABLE_NUM; i++){
4010 if (meta->tables [i].rows == 0)
4012 valid_mask |= (guint64)1 << i;
4014 meta->tables [i].row_size = mono_metadata_compute_size (
4015 meta, i, &meta->tables [i].size_bitfield);
4016 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4018 heapt_size += 24; /* #~ header size */
4019 heapt_size += ntables * 4;
4020 /* make multiple of 4 */
4023 meta_size += heapt_size;
4024 meta->raw_metadata = g_malloc0 (meta_size);
4025 p = (unsigned char*)meta->raw_metadata;
4026 /* the metadata signature */
4027 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4028 /* version numbers and 4 bytes reserved */
4029 int16val = (guint16*)p;
4030 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4031 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4033 /* version string */
4034 int32val = (guint32*)p;
4035 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4037 memcpy (p, meta->version, strlen (meta->version));
4038 p += GUINT32_FROM_LE (*int32val);
4039 align_pointer (meta->raw_metadata, p);
4040 int16val = (guint16*)p;
4041 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4042 *int16val = GUINT16_TO_LE (5); /* number of streams */
4046 * write the stream info.
4048 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4049 table_offset += 3; table_offset &= ~3;
4051 assembly->tstream.index = heapt_size;
4052 for (i = 0; i < 5; ++i) {
4053 int32val = (guint32*)p;
4054 stream_desc [i].stream->offset = table_offset;
4055 *int32val++ = GUINT32_TO_LE (table_offset);
4056 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4057 table_offset += GUINT32_FROM_LE (*int32val);
4058 table_offset += 3; table_offset &= ~3;
4060 strcpy ((char*)p, stream_desc [i].name);
4061 p += strlen (stream_desc [i].name) + 1;
4062 align_pointer (meta->raw_metadata, p);
4065 * now copy the data, the table stream header and contents goes first.
4067 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4068 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4069 int32val = (guint32*)p;
4070 *int32val = GUINT32_TO_LE (0); /* reserved */
4073 *p++ = 2; /* version */
4076 if (meta->idx_string_wide)
4078 if (meta->idx_guid_wide)
4080 if (meta->idx_blob_wide)
4083 *p++ = 1; /* reserved */
4084 int64val = (guint64*)p;
4085 *int64val++ = GUINT64_TO_LE (valid_mask);
4086 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4088 int32val = (guint32*)p;
4089 for (i = 0; i < MONO_TABLE_NUM; i++){
4090 if (meta->tables [i].rows == 0)
4092 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4094 p = (unsigned char*)int32val;
4096 /* sort the tables that still need sorting */
4097 table = &assembly->tables [MONO_TABLE_CONSTANT];
4099 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4100 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4102 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4103 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4105 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4106 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4108 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4109 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4111 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4112 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4113 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4115 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4116 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4118 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4120 /* compress the tables */
4121 for (i = 0; i < MONO_TABLE_NUM; i++){
4124 guint32 bitfield = meta->tables [i].size_bitfield;
4125 if (!meta->tables [i].rows)
4127 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4128 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4129 meta->tables [i].base = (char*)p;
4130 for (row = 1; row <= meta->tables [i].rows; ++row) {
4131 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4132 for (col = 0; col < assembly->tables [i].columns; ++col) {
4133 switch (mono_metadata_table_size (bitfield, col)) {
4135 *p++ = values [col];
4138 *p++ = values [col] & 0xff;
4139 *p++ = (values [col] >> 8) & 0xff;
4142 *p++ = values [col] & 0xff;
4143 *p++ = (values [col] >> 8) & 0xff;
4144 *p++ = (values [col] >> 16) & 0xff;
4145 *p++ = (values [col] >> 24) & 0xff;
4148 g_assert_not_reached ();
4152 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4155 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4156 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4157 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4158 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4159 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4161 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4165 * Some tables in metadata need to be sorted according to some criteria, but
4166 * when methods and fields are first created with reflection, they may be assigned a token
4167 * that doesn't correspond to the final token they will get assigned after the sorting.
4168 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4169 * with the reflection objects that represent them. Once all the tables are set up, the
4170 * reflection objects will contains the correct table index. fixup_method() will fixup the
4171 * tokens for the method with ILGenerator @ilgen.
4174 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4176 guint32 code_idx = GPOINTER_TO_UINT (value);
4177 MonoReflectionILTokenInfo *iltoken;
4178 MonoReflectionFieldBuilder *field;
4179 MonoReflectionCtorBuilder *ctor;
4180 MonoReflectionMethodBuilder *method;
4181 MonoReflectionTypeBuilder *tb;
4182 MonoReflectionArrayMethod *am;
4184 unsigned char *target;
4186 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4187 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4188 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4189 switch (target [3]) {
4190 case MONO_TABLE_FIELD:
4191 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4192 field = (MonoReflectionFieldBuilder *)iltoken->member;
4193 idx = field->table_idx;
4194 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4195 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4196 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4198 g_assert_not_reached ();
4201 case MONO_TABLE_METHOD:
4202 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4203 method = (MonoReflectionMethodBuilder *)iltoken->member;
4204 idx = method->table_idx;
4205 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4206 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4207 idx = ctor->table_idx;
4208 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4209 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4210 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4211 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4213 g_assert_not_reached ();
4216 case MONO_TABLE_TYPEDEF:
4217 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4218 g_assert_not_reached ();
4219 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4220 idx = tb->table_idx;
4222 case MONO_TABLE_MEMBERREF:
4223 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4224 am = (MonoReflectionArrayMethod*)iltoken->member;
4225 idx = am->table_idx;
4226 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4227 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4228 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4229 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4230 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4231 g_assert (m->klass->generic_class || m->klass->generic_container);
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4235 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4236 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4237 g_assert (is_field_on_inst (f));
4239 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4240 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4242 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4244 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4246 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4249 g_assert_not_reached ();
4252 case MONO_TABLE_METHODSPEC:
4253 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4254 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4255 g_assert (mono_method_signature (m)->generic_param_count);
4257 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4259 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4262 g_assert_not_reached ();
4266 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4268 target [0] = idx & 0xff;
4269 target [1] = (idx >> 8) & 0xff;
4270 target [2] = (idx >> 16) & 0xff;
4277 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4278 * value is not known when the table is emitted.
4281 fixup_cattrs (MonoDynamicImage *assembly)
4283 MonoDynamicTable *table;
4285 guint32 type, i, idx, token;
4288 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4290 for (i = 0; i < table->rows; ++i) {
4291 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4293 type = values [MONO_CUSTOM_ATTR_TYPE];
4294 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4295 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4296 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4297 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4300 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4301 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4302 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4303 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4310 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4312 MonoDynamicTable *table;
4315 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4317 alloc_table (table, table->rows);
4318 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4319 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4320 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4321 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4322 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4327 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4329 MonoDynamicTable *table;
4333 char *b = blob_size;
4335 guint32 idx, offset;
4337 if (rsrc->filename) {
4338 name = mono_string_to_utf8 (rsrc->filename);
4339 sname = g_path_get_basename (name);
4341 table = &assembly->tables [MONO_TABLE_FILE];
4343 alloc_table (table, table->rows);
4344 values = table->values + table->next_idx * MONO_FILE_SIZE;
4345 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4346 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4349 mono_sha1_get_digest_from_file (name, hash);
4350 mono_metadata_encode_value (20, b, &b);
4351 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4352 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4354 idx = table->next_idx++;
4356 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4362 data = mono_array_addr (rsrc->data, char, 0);
4363 len = mono_array_length (rsrc->data);
4369 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4370 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4371 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4372 mono_image_add_stream_data (&assembly->resources, data, len);
4376 * The entry should be emitted into the MANIFESTRESOURCE table of
4377 * the main module, but that needs to reference the FILE table
4378 * which isn't emitted yet.
4385 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4389 set_version_from_string (MonoString *version, guint32 *values)
4391 gchar *ver, *p, *str;
4394 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4395 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4396 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4397 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4400 ver = str = mono_string_to_utf8 (version);
4401 for (i = 0; i < 4; ++i) {
4402 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4408 /* handle Revision and Build */
4418 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4422 char *b = blob_size;
4427 len = mono_array_length (pkey);
4428 mono_metadata_encode_value (len, b, &b);
4429 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4430 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4432 assembly->public_key = g_malloc (len);
4433 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4434 assembly->public_key_len = len;
4436 /* Special case: check for ECMA key (16 bytes) */
4437 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4438 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4439 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4440 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4441 /* minimum key size (in 2.0) is 384 bits */
4442 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4444 /* FIXME - verifier */
4445 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4446 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4448 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4454 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4456 MonoDynamicTable *table;
4457 MonoDynamicImage *assembly;
4458 MonoReflectionAssemblyBuilder *assemblyb;
4462 guint32 module_index;
4464 assemblyb = moduleb->assemblyb;
4465 assembly = moduleb->dynamic_image;
4466 domain = mono_object_domain (assemblyb);
4468 /* Emit ASSEMBLY table */
4469 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4470 alloc_table (table, 1);
4471 values = table->values + MONO_ASSEMBLY_SIZE;
4472 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4473 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4474 if (assemblyb->culture) {
4475 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4477 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4479 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4480 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4481 set_version_from_string (assemblyb->version, values);
4483 /* Emit FILE + EXPORTED_TYPE table */
4485 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4487 MonoReflectionModuleBuilder *file_module =
4488 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4489 if (file_module != moduleb) {
4490 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4492 if (file_module->types) {
4493 for (j = 0; j < file_module->num_types; ++j) {
4494 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4495 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4500 if (assemblyb->loaded_modules) {
4501 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4502 MonoReflectionModule *file_module =
4503 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4504 mono_image_fill_file_table (domain, file_module, assembly);
4506 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4509 if (assemblyb->type_forwarders)
4510 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4512 /* Emit MANIFESTRESOURCE table */
4514 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4516 MonoReflectionModuleBuilder *file_module =
4517 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518 /* The table for the main module is emitted later */
4519 if (file_module != moduleb) {
4521 if (file_module->resources) {
4522 int len = mono_array_length (file_module->resources);
4523 for (j = 0; j < len; ++j) {
4524 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4525 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4532 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4535 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4536 * for the modulebuilder @moduleb.
4537 * At the end of the process, method and field tokens are fixed up and the
4538 * on-disk compressed metadata representation is created.
4541 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4543 MonoDynamicTable *table;
4544 MonoDynamicImage *assembly;
4545 MonoReflectionAssemblyBuilder *assemblyb;
4551 assemblyb = moduleb->assemblyb;
4552 assembly = moduleb->dynamic_image;
4553 domain = mono_object_domain (assemblyb);
4555 if (assembly->text_rva)
4558 assembly->text_rva = START_TEXT_RVA;
4560 if (moduleb->is_main) {
4561 mono_image_emit_manifest (moduleb);
4564 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4565 table->rows = 1; /* .<Module> */
4567 alloc_table (table, table->rows);
4569 * Set the first entry.
4571 values = table->values + table->columns;
4572 values [MONO_TYPEDEF_FLAGS] = 0;
4573 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4574 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4575 values [MONO_TYPEDEF_EXTENDS] = 0;
4576 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4577 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4580 * handle global methods
4581 * FIXME: test what to do when global methods are defined in multiple modules.
4583 if (moduleb->global_methods) {
4584 table = &assembly->tables [MONO_TABLE_METHOD];
4585 table->rows += mono_array_length (moduleb->global_methods);
4586 alloc_table (table, table->rows);
4587 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4588 mono_image_get_method_info (
4589 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4591 if (moduleb->global_fields) {
4592 table = &assembly->tables [MONO_TABLE_FIELD];
4593 table->rows += mono_array_length (moduleb->global_fields);
4594 alloc_table (table, table->rows);
4595 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4596 mono_image_get_field_info (
4597 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4600 table = &assembly->tables [MONO_TABLE_MODULE];
4601 alloc_table (table, 1);
4602 mono_image_fill_module_table (domain, moduleb, assembly);
4604 /* Collect all types into a list sorted by their table_idx */
4605 mono_ptr_array_init (types, moduleb->num_types);
4608 for (i = 0; i < moduleb->num_types; ++i) {
4609 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4610 collect_types (&types, type);
4613 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4614 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4615 table->rows += mono_ptr_array_size (types);
4616 alloc_table (table, table->rows);
4619 * Emit type names + namespaces at one place inside the string heap,
4620 * so load_class_names () needs to touch fewer pages.
4622 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4623 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4624 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4626 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4627 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4628 string_heap_insert_mstring (&assembly->sheap, tb->name);
4631 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4632 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4633 mono_image_get_type_info (domain, type, assembly);
4637 * table->rows is already set above and in mono_image_fill_module_table.
4639 /* add all the custom attributes at the end, once all the indexes are stable */
4640 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4642 /* CAS assembly permissions */
4643 if (assemblyb->permissions_minimum)
4644 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4645 if (assemblyb->permissions_optional)
4646 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4647 if (assemblyb->permissions_refused)
4648 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4650 module_add_cattrs (assembly, moduleb);
4653 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4655 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4656 * the final tokens and don't need another fixup pass. */
4658 if (moduleb->global_methods) {
4659 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4660 MonoReflectionMethodBuilder *mb = mono_array_get (
4661 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4662 mono_image_add_methodimpl (assembly, mb);
4666 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4668 if (type->methods) {
4669 for (j = 0; j < type->num_methods; ++j) {
4670 MonoReflectionMethodBuilder *mb = mono_array_get (
4671 type->methods, MonoReflectionMethodBuilder*, j);
4673 mono_image_add_methodimpl (assembly, mb);
4678 mono_ptr_array_destroy (types);
4680 fixup_cattrs (assembly);
4683 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4686 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4688 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4691 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4695 guint32 import_lookup_table;
4699 guint32 import_address_table_rva;
4707 #ifndef DISABLE_REFLECTION_EMIT
4710 * mono_image_insert_string:
4711 * @module: module builder object
4714 * Insert @str into the user string stream of @module.
4717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4719 MonoDynamicImage *assembly;
4724 MONO_ARCH_SAVE_REGS;
4726 if (!module->dynamic_image)
4727 mono_image_module_basic_init (module);
4729 assembly = module->dynamic_image;
4731 if (assembly->save) {
4732 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4733 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4736 char *swapped = g_malloc (2 * mono_string_length (str));
4737 const char *p = (const char*)mono_string_chars (str);
4739 swap_with_size (swapped, p, 2, mono_string_length (str));
4740 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4744 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4746 mono_image_add_stream_data (&assembly->us, "", 1);
4748 idx = assembly->us.index ++;
4751 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4753 return MONO_TOKEN_STRING | idx;
4757 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4761 MonoMethodSignature *sig;
4763 klass = obj->vtable->klass;
4764 if (strcmp (klass->name, "MonoMethod") == 0) {
4765 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4766 MonoMethodSignature *old;
4767 guint32 sig_token, parent;
4770 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4772 nargs = mono_array_length (opt_param_types);
4773 old = mono_method_signature (method);
4774 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4776 sig->hasthis = old->hasthis;
4777 sig->explicit_this = old->explicit_this;
4778 sig->call_convention = old->call_convention;
4779 sig->generic_param_count = old->generic_param_count;
4780 sig->param_count = old->param_count + nargs;
4781 sig->sentinelpos = old->param_count;
4782 sig->ret = old->ret;
4784 for (i = 0; i < old->param_count; i++)
4785 sig->params [i] = old->params [i];
4787 for (i = 0; i < nargs; i++) {
4788 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4789 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4792 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4793 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4794 parent >>= MONO_TYPEDEFORREF_BITS;
4796 parent <<= MONO_MEMBERREF_PARENT_BITS;
4797 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4799 sig_token = method_encode_signature (assembly, sig);
4800 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4801 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4802 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4803 ReflectionMethodBuilder rmb;
4804 guint32 parent, sig_token;
4805 int nopt_args, nparams, ngparams, i;
4808 reflection_methodbuilder_from_method_builder (&rmb, mb);
4809 rmb.opt_types = opt_param_types;
4810 nopt_args = mono_array_length (opt_param_types);
4812 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4813 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4814 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4816 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4817 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4818 sig->call_convention = rmb.call_conv;
4819 sig->generic_param_count = ngparams;
4820 sig->param_count = nparams + nopt_args;
4821 sig->sentinelpos = nparams;
4822 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4824 for (i = 0; i < nparams; i++) {
4825 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4826 sig->params [i] = mono_reflection_type_get_handle (rt);
4829 for (i = 0; i < nopt_args; i++) {
4830 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4831 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4834 sig_token = method_builder_encode_signature (assembly, &rmb);
4836 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4837 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4839 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4840 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4842 name = mono_string_to_utf8 (rmb.name);
4843 token = mono_image_get_varargs_method_token (
4844 assembly, parent, name, sig_token);
4847 g_error ("requested method token for %s\n", klass->name);
4850 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4851 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4856 * mono_image_create_token:
4857 * @assembly: a dynamic assembly
4859 * @register_token: Whenever to register the token in the assembly->tokens hash.
4861 * Get a token to insert in the IL code stream for the given MemberInfo.
4862 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4863 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4867 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4868 gboolean create_methodspec, gboolean register_token)
4873 klass = obj->vtable->klass;
4875 /* Check for user defined reflection objects */
4876 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4877 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4878 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4880 if (strcmp (klass->name, "MethodBuilder") == 0) {
4881 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4884 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4885 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4887 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4888 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4889 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4890 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4891 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4893 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4894 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4896 token = mono_image_get_ctorbuilder_token (assembly, mb);
4897 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4898 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4899 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4900 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4901 if (tb->generic_params) {
4902 token = mono_image_get_generic_field_token (assembly, fb);
4904 if ((tb->module->dynamic_image == assembly)) {
4905 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4907 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4910 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4911 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4912 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4913 } else if (strcmp (klass->name, "MonoType") == 0) {
4914 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4915 MonoClass *mc = mono_class_from_mono_type (type);
4916 if (!mono_class_init (mc))
4917 mono_raise_exception (mono_class_get_exception_for_failure (mc));
4919 token = mono_metadata_token_from_dor (
4920 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4921 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4922 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4923 token = mono_metadata_token_from_dor (
4924 mono_image_typedef_or_ref (assembly, type));
4925 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4926 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4927 token = mono_metadata_token_from_dor (
4928 mono_image_typedef_or_ref (assembly, type));
4929 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4930 strcmp (klass->name, "MonoMethod") == 0 ||
4931 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4932 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4933 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4934 if (m->method->is_inflated) {
4935 if (create_methodspec)
4936 token = mono_image_get_methodspec_token (assembly, m->method);
4938 token = mono_image_get_inflated_method_token (assembly, m->method);
4939 } else if ((m->method->klass->image == &assembly->image) &&
4940 !m->method->klass->generic_class) {
4941 static guint32 method_table_idx = 0xffffff;
4942 if (m->method->klass->wastypebuilder) {
4943 /* we use the same token as the one that was assigned
4944 * to the Methodbuilder.
4945 * FIXME: do the equivalent for Fields.
4947 token = m->method->token;
4950 * Each token should have a unique index, but the indexes are
4951 * assigned by managed code, so we don't know about them. An
4952 * easy solution is to count backwards...
4954 method_table_idx --;
4955 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4958 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4960 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4961 } else if (strcmp (klass->name, "MonoField") == 0) {
4962 MonoReflectionField *f = (MonoReflectionField *)obj;
4963 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4964 static guint32 field_table_idx = 0xffffff;
4966 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4968 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
4970 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4971 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4972 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4973 token = mono_image_get_array_token (assembly, m);
4974 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4975 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4976 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4977 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4978 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979 token = mono_metadata_token_from_dor (
4980 mono_image_typedef_or_ref (assembly, type));
4981 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4982 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4983 token = mono_image_get_field_on_inst_token (assembly, f);
4984 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4985 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4986 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4987 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4988 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4989 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4990 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4991 MonoReflectionType *type = (MonoReflectionType *)obj;
4992 token = mono_metadata_token_from_dor (
4993 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4995 g_error ("requested token for %s\n", klass->name);
4999 mono_image_register_token (assembly, token, obj);
5005 * mono_image_register_token:
5007 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5008 * the Module.ResolveXXXToken () methods to work.
5011 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5013 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5015 /* There could be multiple MethodInfo objects with the same token */
5016 //g_assert (prev == obj);
5018 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5022 static MonoDynamicImage*
5023 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5025 static const guchar entrycode [16] = {0xff, 0x25, 0};
5026 MonoDynamicImage *image;
5029 const char *version;
5031 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5032 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5034 version = mono_get_runtime_info ()->runtime_version;
5037 /* The MonoGHashTable's need GC tracking */
5038 image = GC_MALLOC (sizeof (MonoDynamicImage));
5040 image = g_new0 (MonoDynamicImage, 1);
5043 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5045 /*g_print ("created image %p\n", image);*/
5046 /* keep in sync with image.c */
5047 image->image.name = assembly_name;
5048 image->image.assembly_name = image->image.name; /* they may be different */
5049 image->image.module_name = module_name;
5050 image->image.version = g_strdup (version);
5051 image->image.md_version_major = 1;
5052 image->image.md_version_minor = 1;
5053 image->image.dynamic = TRUE;
5055 image->image.references = g_new0 (MonoAssembly*, 1);
5056 image->image.references [0] = NULL;
5058 mono_image_init (&image->image);
5060 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5061 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5062 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5063 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5064 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5065 image->handleref = g_hash_table_new (NULL, NULL);
5066 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5067 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5068 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5069 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5070 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5071 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5072 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5073 image->gen_params = g_ptr_array_new ();
5075 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5076 string_heap_init (&image->sheap);
5077 mono_image_add_stream_data (&image->us, "", 1);
5078 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5079 /* import tables... */
5080 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5081 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5082 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5083 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5084 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5085 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5086 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5087 stream_data_align (&image->code);
5089 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5091 for (i=0; i < MONO_TABLE_NUM; ++i) {
5092 image->tables [i].next_idx = 1;
5093 image->tables [i].columns = table_sizes [i];
5096 image->image.assembly = (MonoAssembly*)assembly;
5097 image->run = assembly->run;
5098 image->save = assembly->save;
5099 image->pe_kind = 0x1; /* ILOnly */
5100 image->machine = 0x14c; /* I386 */
5102 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5109 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5115 mono_dynamic_image_free (MonoDynamicImage *image)
5117 MonoDynamicImage *di = image;
5122 mono_g_hash_table_destroy (di->methodspec);
5124 g_hash_table_destroy (di->typespec);
5126 g_hash_table_destroy (di->typeref);
5128 g_hash_table_destroy (di->handleref);
5129 if (di->handleref_managed)
5130 mono_g_hash_table_destroy (di->handleref_managed);
5132 mono_g_hash_table_destroy (di->tokens);
5133 if (di->generic_def_objects)
5134 mono_g_hash_table_destroy (di->generic_def_objects);
5135 if (di->blob_cache) {
5136 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5137 g_hash_table_destroy (di->blob_cache);
5139 if (di->standalonesig_cache)
5140 g_hash_table_destroy (di->standalonesig_cache);
5141 for (list = di->array_methods; list; list = list->next) {
5142 ArrayMethod *am = (ArrayMethod *)list->data;
5147 g_list_free (di->array_methods);
5148 if (di->gen_params) {
5149 for (i = 0; i < di->gen_params->len; i++) {
5150 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5151 if (entry->gparam->type.type) {
5152 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5153 g_free ((char*)mono_generic_param_info (param)->name);
5156 mono_gc_deregister_root ((char*) &entry->gparam);
5159 g_ptr_array_free (di->gen_params, TRUE);
5161 if (di->token_fixups)
5162 mono_g_hash_table_destroy (di->token_fixups);
5163 if (di->method_to_table_idx)
5164 g_hash_table_destroy (di->method_to_table_idx);
5165 if (di->field_to_table_idx)
5166 g_hash_table_destroy (di->field_to_table_idx);
5167 if (di->method_aux_hash)
5168 g_hash_table_destroy (di->method_aux_hash);
5169 if (di->vararg_aux_hash)
5170 g_hash_table_destroy (di->vararg_aux_hash);
5171 g_free (di->strong_name);
5172 g_free (di->win32_res);
5174 g_free (di->public_key);
5176 /*g_print ("string heap destroy for image %p\n", di);*/
5177 mono_dynamic_stream_reset (&di->sheap);
5178 mono_dynamic_stream_reset (&di->code);
5179 mono_dynamic_stream_reset (&di->resources);
5180 mono_dynamic_stream_reset (&di->us);
5181 mono_dynamic_stream_reset (&di->blob);
5182 mono_dynamic_stream_reset (&di->tstream);
5183 mono_dynamic_stream_reset (&di->guid);
5184 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5185 g_free (di->tables [i].values);
5189 #ifndef DISABLE_REFLECTION_EMIT
5192 * mono_image_basic_init:
5193 * @assembly: an assembly builder object
5195 * Create the MonoImage that represents the assembly builder and setup some
5196 * of the helper hash table and the basic metadata streams.
5199 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5201 MonoDynamicAssembly *assembly;
5202 MonoDynamicImage *image;
5203 MonoDomain *domain = mono_object_domain (assemblyb);
5205 MONO_ARCH_SAVE_REGS;
5207 if (assemblyb->dynamic_assembly)
5211 /* assembly->assembly.image might be GC allocated */
5212 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5214 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5217 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5219 assembly->assembly.ref_count = 1;
5220 assembly->assembly.dynamic = TRUE;
5221 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5222 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5223 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5224 if (assemblyb->culture)
5225 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5227 assembly->assembly.aname.culture = g_strdup ("");
5229 if (assemblyb->version) {
5230 char *vstr = mono_string_to_utf8 (assemblyb->version);
5231 char **version = g_strsplit (vstr, ".", 4);
5232 char **parts = version;
5233 assembly->assembly.aname.major = atoi (*parts++);
5234 assembly->assembly.aname.minor = atoi (*parts++);
5235 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5236 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5238 g_strfreev (version);
5241 assembly->assembly.aname.major = 0;
5242 assembly->assembly.aname.minor = 0;
5243 assembly->assembly.aname.build = 0;
5244 assembly->assembly.aname.revision = 0;
5247 assembly->run = assemblyb->access != 2;
5248 assembly->save = assemblyb->access != 1;
5249 assembly->domain = domain;
5251 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5252 image->initial_image = TRUE;
5253 assembly->assembly.aname.name = image->image.name;
5254 assembly->assembly.image = &image->image;
5255 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5256 /* -1 to correct for the trailing NULL byte */
5257 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5258 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5260 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5263 mono_domain_assemblies_lock (domain);
5264 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5265 mono_domain_assemblies_unlock (domain);
5267 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5269 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5271 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5274 #endif /* !DISABLE_REFLECTION_EMIT */
5276 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5279 calc_section_size (MonoDynamicImage *assembly)
5283 /* alignment constraints */
5284 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5285 g_assert ((assembly->code.index % 4) == 0);
5286 assembly->meta_size += 3;
5287 assembly->meta_size &= ~3;
5288 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5289 g_assert ((assembly->resources.index % 4) == 0);
5291 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5292 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5295 if (assembly->win32_res) {
5296 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5298 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5299 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5303 assembly->sections [MONO_SECTION_RELOC].size = 12;
5304 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5314 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5318 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5320 ResTreeNode *t1 = (ResTreeNode*)a;
5321 ResTreeNode *t2 = (ResTreeNode*)b;
5323 return t1->id - t2->id;
5327 * resource_tree_create:
5329 * Organize the resources into a resource tree.
5331 static ResTreeNode *
5332 resource_tree_create (MonoArray *win32_resources)
5334 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5338 tree = g_new0 (ResTreeNode, 1);
5340 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5341 MonoReflectionWin32Resource *win32_res =
5342 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5346 /* FIXME: BUG: this stores managed references in unmanaged memory */
5347 lang_node = g_new0 (ResTreeNode, 1);
5348 lang_node->id = win32_res->lang_id;
5349 lang_node->win32_res = win32_res;
5351 /* Create type node if neccesary */
5353 for (l = tree->children; l; l = l->next)
5354 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5355 type_node = (ResTreeNode*)l->data;
5360 type_node = g_new0 (ResTreeNode, 1);
5361 type_node->id = win32_res->res_type;
5364 * The resource types have to be sorted otherwise
5365 * Windows Explorer can't display the version information.
5367 tree->children = g_slist_insert_sorted (tree->children,
5368 type_node, resource_tree_compare_by_id);
5371 /* Create res node if neccesary */
5373 for (l = type_node->children; l; l = l->next)
5374 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5375 res_node = (ResTreeNode*)l->data;
5380 res_node = g_new0 (ResTreeNode, 1);
5381 res_node->id = win32_res->res_id;
5382 type_node->children = g_slist_append (type_node->children, res_node);
5385 res_node->children = g_slist_append (res_node->children, lang_node);
5392 * resource_tree_encode:
5394 * Encode the resource tree into the format used in the PE file.
5397 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5400 MonoPEResourceDir dir;
5401 MonoPEResourceDirEntry dir_entry;
5402 MonoPEResourceDataEntry data_entry;
5404 guint32 res_id_entries;
5407 * For the format of the resource directory, see the article
5408 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5412 memset (&dir, 0, sizeof (dir));
5413 memset (&dir_entry, 0, sizeof (dir_entry));
5414 memset (&data_entry, 0, sizeof (data_entry));
5416 g_assert (sizeof (dir) == 16);
5417 g_assert (sizeof (dir_entry) == 8);
5418 g_assert (sizeof (data_entry) == 16);
5420 node->offset = p - begin;
5422 /* IMAGE_RESOURCE_DIRECTORY */
5423 res_id_entries = g_slist_length (node->children);
5424 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5426 memcpy (p, &dir, sizeof (dir));
5429 /* Reserve space for entries */
5431 p += sizeof (dir_entry) * res_id_entries;
5433 /* Write children */
5434 for (l = node->children; l; l = l->next) {
5435 ResTreeNode *child = (ResTreeNode*)l->data;
5437 if (child->win32_res) {
5440 child->offset = p - begin;
5442 /* IMAGE_RESOURCE_DATA_ENTRY */
5443 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5444 size = mono_array_length (child->win32_res->res_data);
5445 data_entry.rde_size = GUINT32_TO_LE (size);
5447 memcpy (p, &data_entry, sizeof (data_entry));
5448 p += sizeof (data_entry);
5450 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5453 resource_tree_encode (child, begin, p, &p);
5457 /* IMAGE_RESOURCE_ENTRY */
5458 for (l = node->children; l; l = l->next) {
5459 ResTreeNode *child = (ResTreeNode*)l->data;
5461 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5462 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5464 memcpy (entries, &dir_entry, sizeof (dir_entry));
5465 entries += sizeof (dir_entry);
5472 resource_tree_free (ResTreeNode * node)
5475 for (list = node->children; list; list = list->next)
5476 resource_tree_free ((ResTreeNode*)list->data);
5477 g_slist_free(node->children);
5482 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5487 MonoReflectionWin32Resource *win32_res;
5490 if (!assemblyb->win32_resources)
5494 * Resources are stored in a three level tree inside the PE file.
5495 * - level one contains a node for each type of resource
5496 * - level two contains a node for each resource
5497 * - level three contains a node for each instance of a resource for a
5498 * specific language.
5501 tree = resource_tree_create (assemblyb->win32_resources);
5503 /* Estimate the size of the encoded tree */
5505 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5506 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5507 size += mono_array_length (win32_res->res_data);
5509 /* Directory structure */
5510 size += mono_array_length (assemblyb->win32_resources) * 256;
5511 p = buf = g_malloc (size);
5513 resource_tree_encode (tree, p, p, &p);
5515 g_assert (p - buf <= size);
5517 assembly->win32_res = g_malloc (p - buf);
5518 assembly->win32_res_size = p - buf;
5519 memcpy (assembly->win32_res, buf, p - buf);
5522 resource_tree_free (tree);
5526 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5528 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5531 p += sizeof (MonoPEResourceDir);
5532 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5533 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5534 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5535 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5536 fixup_resource_directory (res_section, child, rva);
5538 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5539 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5542 p += sizeof (MonoPEResourceDirEntry);
5547 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5550 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5551 g_error ("WriteFile returned %d\n", GetLastError ());
5555 * mono_image_create_pefile:
5556 * @mb: a module builder object
5558 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5559 * assembly->pefile where it can be easily retrieved later in chunks.
5562 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5564 MonoMSDOSHeader *msdos;
5565 MonoDotNetHeader *header;
5566 MonoSectionTable *section;
5567 MonoCLIHeader *cli_header;
5568 guint32 size, image_size, virtual_base, text_offset;
5569 guint32 header_start, section_start, file_offset, virtual_offset;
5570 MonoDynamicImage *assembly;
5571 MonoReflectionAssemblyBuilder *assemblyb;
5572 MonoDynamicStream pefile_stream = {0};
5573 MonoDynamicStream *pefile = &pefile_stream;
5575 guint32 *rva, value;
5577 static const unsigned char msheader[] = {
5578 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5579 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5582 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5583 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5584 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5585 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5588 assemblyb = mb->assemblyb;
5590 mono_image_basic_init (assemblyb);
5591 assembly = mb->dynamic_image;
5593 assembly->pe_kind = assemblyb->pe_kind;
5594 assembly->machine = assemblyb->machine;
5595 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5596 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5598 mono_image_build_metadata (mb);
5600 if (mb->is_main && assemblyb->resources) {
5601 int len = mono_array_length (assemblyb->resources);
5602 for (i = 0; i < len; ++i)
5603 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5606 if (mb->resources) {
5607 int len = mono_array_length (mb->resources);
5608 for (i = 0; i < len; ++i)
5609 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5612 build_compressed_metadata (assembly);
5615 assembly_add_win32_resources (assembly, assemblyb);
5617 nsections = calc_section_size (assembly);
5619 /* The DOS header and stub */
5620 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5621 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5623 /* the dotnet header */
5624 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5626 /* the section tables */
5627 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5629 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5630 virtual_offset = VIRT_ALIGN;
5633 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5634 if (!assembly->sections [i].size)
5637 file_offset += FILE_ALIGN - 1;
5638 file_offset &= ~(FILE_ALIGN - 1);
5639 virtual_offset += VIRT_ALIGN - 1;
5640 virtual_offset &= ~(VIRT_ALIGN - 1);
5642 assembly->sections [i].offset = file_offset;
5643 assembly->sections [i].rva = virtual_offset;
5645 file_offset += assembly->sections [i].size;
5646 virtual_offset += assembly->sections [i].size;
5647 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5650 file_offset += FILE_ALIGN - 1;
5651 file_offset &= ~(FILE_ALIGN - 1);
5653 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5655 /* back-patch info */
5656 msdos = (MonoMSDOSHeader*)pefile->data;
5657 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5659 header = (MonoDotNetHeader*)(pefile->data + header_start);
5660 header->pesig [0] = 'P';
5661 header->pesig [1] = 'E';
5663 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5664 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5665 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5666 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5667 if (assemblyb->pekind == 1) {
5669 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5672 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5675 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5677 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5678 header->pe.pe_major = 6;
5679 header->pe.pe_minor = 0;
5680 size = assembly->sections [MONO_SECTION_TEXT].size;
5681 size += FILE_ALIGN - 1;
5682 size &= ~(FILE_ALIGN - 1);
5683 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5684 size = assembly->sections [MONO_SECTION_RSRC].size;
5685 size += FILE_ALIGN - 1;
5686 size &= ~(FILE_ALIGN - 1);
5687 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5688 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5689 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5690 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5691 /* pe_rva_entry_point always at the beginning of the text section */
5692 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5694 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5695 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5696 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5697 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5698 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5699 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5700 size = section_start;
5701 size += FILE_ALIGN - 1;
5702 size &= ~(FILE_ALIGN - 1);
5703 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5705 size += VIRT_ALIGN - 1;
5706 size &= ~(VIRT_ALIGN - 1);
5707 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5710 // Translate the PEFileKind value to the value expected by the Windows loader
5716 // PEFileKinds.Dll == 1
5717 // PEFileKinds.ConsoleApplication == 2
5718 // PEFileKinds.WindowApplication == 3
5721 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5722 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5724 if (assemblyb->pekind == 3)
5729 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5731 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5732 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5733 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5734 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5735 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5736 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5738 /* fill data directory entries */
5740 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5741 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5743 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5744 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5746 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5747 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5748 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5749 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5750 /* patch entrypoint name */
5751 if (assemblyb->pekind == 1)
5752 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5754 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5755 /* patch imported function RVA name */
5756 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5757 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5759 /* the import table */
5760 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5761 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5762 /* patch imported dll RVA name and other entries in the dir */
5763 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5765 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5766 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5767 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5768 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5770 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5771 value = (assembly->text_rva + assembly->imp_names_offset);
5772 *p++ = (value) & 0xff;
5773 *p++ = (value >> 8) & (0xff);
5774 *p++ = (value >> 16) & (0xff);
5775 *p++ = (value >> 24) & (0xff);
5777 /* the CLI header info */
5778 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5779 cli_header->ch_size = GUINT32_FROM_LE (72);
5780 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5781 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5782 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5783 if (assemblyb->entry_point) {
5784 guint32 table_idx = 0;
5785 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5786 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5787 table_idx = methodb->table_idx;
5789 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5791 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5793 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5795 /* The embedded managed resources */
5796 text_offset = assembly->text_rva + assembly->code.index;
5797 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5798 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5799 text_offset += assembly->resources.index;
5800 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5801 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5802 text_offset += assembly->meta_size;
5803 if (assembly->strong_name_size) {
5804 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5805 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5806 text_offset += assembly->strong_name_size;
5809 /* write the section tables and section content */
5810 section = (MonoSectionTable*)(pefile->data + section_start);
5811 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5812 static const char section_names [][7] = {
5813 ".text", ".rsrc", ".reloc"
5815 if (!assembly->sections [i].size)
5817 strcpy (section->st_name, section_names [i]);
5818 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5819 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5820 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5821 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5822 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5823 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5824 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5828 checked_write_file (file, pefile->data, pefile->index);
5830 mono_dynamic_stream_reset (pefile);
5832 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5833 if (!assembly->sections [i].size)
5836 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5837 g_error ("SetFilePointer returned %d\n", GetLastError ());
5840 case MONO_SECTION_TEXT:
5841 /* patch entry point */
5842 p = (guchar*)(assembly->code.data + 2);
5843 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5844 *p++ = (value) & 0xff;
5845 *p++ = (value >> 8) & 0xff;
5846 *p++ = (value >> 16) & 0xff;
5847 *p++ = (value >> 24) & 0xff;
5849 checked_write_file (file, assembly->code.data, assembly->code.index);
5850 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5851 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5852 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5855 g_free (assembly->image.raw_metadata);
5857 case MONO_SECTION_RELOC: {
5861 guint16 type_and_offset;
5865 g_assert (sizeof (reloc) == 12);
5867 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5868 reloc.block_size = GUINT32_FROM_LE (12);
5871 * the entrypoint is always at the start of the text section
5872 * 3 is IMAGE_REL_BASED_HIGHLOW
5873 * 2 is patch_size_rva - text_rva
5875 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5878 checked_write_file (file, &reloc, sizeof (reloc));
5882 case MONO_SECTION_RSRC:
5883 if (assembly->win32_res) {
5885 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5886 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5887 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5891 g_assert_not_reached ();
5895 /* check that the file is properly padded */
5896 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5897 g_error ("SetFilePointer returned %d\n", GetLastError ());
5898 if (! SetEndOfFile (file))
5899 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5901 mono_dynamic_stream_reset (&assembly->code);
5902 mono_dynamic_stream_reset (&assembly->us);
5903 mono_dynamic_stream_reset (&assembly->blob);
5904 mono_dynamic_stream_reset (&assembly->guid);
5905 mono_dynamic_stream_reset (&assembly->sheap);
5907 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5908 g_hash_table_destroy (assembly->blob_cache);
5909 assembly->blob_cache = NULL;
5912 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5915 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5917 g_assert_not_reached ();
5920 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5922 #ifndef DISABLE_REFLECTION_EMIT
5924 MonoReflectionModule *
5925 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5929 MonoImageOpenStatus status;
5930 MonoDynamicAssembly *assembly;
5931 guint32 module_count;
5932 MonoImage **new_modules;
5933 gboolean *new_modules_loaded;
5935 name = mono_string_to_utf8 (fileName);
5937 image = mono_image_open (name, &status);
5940 if (status == MONO_IMAGE_ERROR_ERRNO)
5941 exc = mono_get_exception_file_not_found (fileName);
5943 exc = mono_get_exception_bad_image_format (name);
5945 mono_raise_exception (exc);
5950 assembly = ab->dynamic_assembly;
5951 image->assembly = (MonoAssembly*)assembly;
5953 module_count = image->assembly->image->module_count;
5954 new_modules = g_new0 (MonoImage *, module_count + 1);
5955 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5957 if (image->assembly->image->modules)
5958 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5959 if (image->assembly->image->modules_loaded)
5960 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5961 new_modules [module_count] = image;
5962 new_modules_loaded [module_count] = TRUE;
5963 mono_image_addref (image);
5965 g_free (image->assembly->image->modules);
5966 image->assembly->image->modules = new_modules;
5967 image->assembly->image->modules_loaded = new_modules_loaded;
5968 image->assembly->image->module_count ++;
5970 mono_assembly_load_references (image, &status);
5972 mono_image_close (image);
5973 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5976 return mono_module_get_object (mono_domain_get (), image);
5979 #endif /* DISABLE_REFLECTION_EMIT */
5982 * We need to return always the same object for MethodInfo, FieldInfo etc..
5983 * but we need to consider the reflected type.
5984 * type uses a different hash, since it uses custom hash/equal functions.
5989 MonoClass *refclass;
5993 reflected_equal (gconstpointer a, gconstpointer b) {
5994 const ReflectedEntry *ea = a;
5995 const ReflectedEntry *eb = b;
5997 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6001 reflected_hash (gconstpointer a) {
6002 const ReflectedEntry *ea = a;
6003 return mono_aligned_addr_hash (ea->item);
6006 #define CHECK_OBJECT(t,p,k) \
6012 mono_domain_lock (domain); \
6013 if (!domain->refobject_hash) \
6014 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6015 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6016 mono_domain_unlock (domain); \
6019 mono_domain_unlock (domain); \
6022 #ifdef HAVE_BOEHM_GC
6023 /* ReflectedEntry doesn't need to be GC tracked */
6024 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6025 #define FREE_REFENTRY(entry) g_free ((entry))
6026 #define REFENTRY_REQUIRES_CLEANUP
6028 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6030 #define FREE_REFENTRY(entry)
6033 #define CACHE_OBJECT(t,p,o,k) \
6036 ReflectedEntry pe; \
6038 pe.refclass = (k); \
6039 mono_domain_lock (domain); \
6040 if (!domain->refobject_hash) \
6041 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6042 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6044 ReflectedEntry *e = ALLOC_REFENTRY; \
6046 e->refclass = (k); \
6047 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6050 mono_domain_unlock (domain); \
6055 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6057 mono_domain_lock (domain);
6058 if (domain->refobject_hash) {
6060 gpointer orig_pe, orig_value;
6063 pe.refclass = klass;
6064 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6065 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6066 FREE_REFENTRY (orig_pe);
6069 mono_domain_unlock (domain);
6072 #ifdef REFENTRY_REQUIRES_CLEANUP
6074 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6076 FREE_REFENTRY (key);
6081 mono_reflection_cleanup_domain (MonoDomain *domain)
6083 if (domain->refobject_hash) {
6084 /*let's avoid scanning the whole hashtable if not needed*/
6085 #ifdef REFENTRY_REQUIRES_CLEANUP
6086 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6088 mono_g_hash_table_destroy (domain->refobject_hash);
6089 domain->refobject_hash = NULL;
6093 #ifndef DISABLE_REFLECTION_EMIT
6095 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6097 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6101 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6103 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6107 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6109 MonoDynamicImage *image = moduleb->dynamic_image;
6110 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6114 MonoImage **new_modules;
6116 char *name, *fqname;
6118 * FIXME: we already created an image in mono_image_basic_init (), but
6119 * we don't know which module it belongs to, since that is only
6120 * determined at assembly save time.
6122 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6123 name = mono_string_to_utf8 (ab->name);
6124 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6125 if (!mono_error_ok (&error)) {
6127 mono_error_raise_exception (&error);
6129 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6131 moduleb->module.image = &image->image;
6132 moduleb->dynamic_image = image;
6133 register_module (mono_object_domain (moduleb), moduleb, image);
6135 /* register the module with the assembly */
6136 ass = ab->dynamic_assembly->assembly.image;
6137 module_count = ass->module_count;
6138 new_modules = g_new0 (MonoImage *, module_count + 1);
6141 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6142 new_modules [module_count] = &image->image;
6143 mono_image_addref (&image->image);
6145 g_free (ass->modules);
6146 ass->modules = new_modules;
6147 ass->module_count ++;
6152 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6154 MonoDynamicImage *image = moduleb->dynamic_image;
6156 g_assert (type->type);
6157 image->wrappers_type = mono_class_from_mono_type (type->type);
6163 * mono_assembly_get_object:
6164 * @domain: an app domain
6165 * @assembly: an assembly
6167 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6169 MonoReflectionAssembly*
6170 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6172 static MonoClass *assembly_type;
6173 MonoReflectionAssembly *res;
6175 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6176 if (!assembly_type) {
6177 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6179 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6181 assembly_type = class;
6183 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6184 res->assembly = assembly;
6186 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6191 MonoReflectionModule*
6192 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6194 static MonoClass *module_type;
6195 MonoReflectionModule *res;
6198 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6200 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6202 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6204 module_type = class;
6206 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6209 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6211 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6212 basename = g_path_get_basename (image->name);
6213 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6214 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6218 if (image->assembly->image == image) {
6219 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6223 if (image->assembly->image->modules) {
6224 for (i = 0; i < image->assembly->image->module_count; i++) {
6225 if (image->assembly->image->modules [i] == image)
6226 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6228 g_assert (res->token);
6232 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6235 MonoReflectionModule*
6236 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6238 static MonoClass *module_type;
6239 MonoReflectionModule *res;
6240 MonoTableInfo *table;
6241 guint32 cols [MONO_FILE_SIZE];
6243 guint32 i, name_idx;
6247 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6249 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6251 module_type = class;
6253 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6255 table = &image->tables [MONO_TABLE_FILE];
6256 g_assert (table_index < table->rows);
6257 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6260 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6261 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6263 /* Check whenever the row has a corresponding row in the moduleref table */
6264 table = &image->tables [MONO_TABLE_MODULEREF];
6265 for (i = 0; i < table->rows; ++i) {
6266 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6267 val = mono_metadata_string_heap (image, name_idx);
6268 if (strcmp (val, name) == 0)
6269 res->image = image->modules [i];
6272 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6273 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6274 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6275 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6276 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6282 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6284 if ((t1->type != t2->type) ||
6285 (t1->byref != t2->byref))
6289 case MONO_TYPE_VOID:
6290 case MONO_TYPE_BOOLEAN:
6291 case MONO_TYPE_CHAR:
6302 case MONO_TYPE_STRING:
6305 case MONO_TYPE_OBJECT:
6306 case MONO_TYPE_TYPEDBYREF:
6308 case MONO_TYPE_VALUETYPE:
6309 case MONO_TYPE_CLASS:
6310 case MONO_TYPE_SZARRAY:
6311 return t1->data.klass == t2->data.klass;
6313 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6314 case MONO_TYPE_ARRAY:
6315 if (t1->data.array->rank != t2->data.array->rank)
6317 return t1->data.array->eklass == t2->data.array->eklass;
6318 case MONO_TYPE_GENERICINST: {
6320 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6321 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6322 if (i1->type_argc != i2->type_argc)
6324 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6325 &t2->data.generic_class->container_class->byval_arg))
6327 /* FIXME: we should probably just compare the instance pointers directly. */
6328 for (i = 0; i < i1->type_argc; ++i) {
6329 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6335 case MONO_TYPE_MVAR:
6336 return t1->data.generic_param == t2->data.generic_param;
6338 g_error ("implement type compare for %0x!", t1->type);
6346 mymono_metadata_type_hash (MonoType *t1)
6352 hash |= t1->byref << 6; /* do not collide with t1->type values */
6354 case MONO_TYPE_VALUETYPE:
6355 case MONO_TYPE_CLASS:
6356 case MONO_TYPE_SZARRAY:
6357 /* check if the distribution is good enough */
6358 return ((hash << 5) - hash) ^ mono_aligned_addr_hash (t1->data.klass);
6360 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6361 case MONO_TYPE_GENERICINST: {
6363 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6364 hash += g_str_hash (t1->data.generic_class->container_class->name);
6366 for (i = 0; i < inst->type_argc; ++i) {
6367 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6373 case MONO_TYPE_MVAR:
6374 return ((hash << 5) - hash) ^ GPOINTER_TO_UINT (t1->data.generic_param);
6380 verify_safe_for_managed_space (MonoType *type)
6382 switch (type->type) {
6384 case MONO_TYPE_ARRAY:
6385 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6387 return verify_safe_for_managed_space (type->data.type);
6388 case MONO_TYPE_SZARRAY:
6389 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6390 case MONO_TYPE_GENERICINST: {
6391 MonoGenericInst *inst = type->data.generic_class->inst;
6395 for (i = 0; i < inst->type_argc; ++i)
6396 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6402 case MONO_TYPE_MVAR:
6409 mono_type_normalize (MonoType *type)
6412 MonoGenericClass *gclass;
6413 MonoGenericInst *ginst;
6415 MonoGenericContainer *gcontainer;
6416 MonoType **argv = NULL;
6417 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6419 if (type->type != MONO_TYPE_GENERICINST)
6422 gclass = type->data.generic_class;
6423 ginst = gclass->context.class_inst;
6424 if (!ginst->is_open)
6427 gtd = gclass->container_class;
6428 gcontainer = gtd->generic_container;
6429 argv = g_newa (MonoType*, ginst->type_argc);
6431 for (i = 0; i < ginst->type_argc; ++i) {
6432 MonoType *t = ginst->type_argv [i], *norm;
6433 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6434 is_denorm_gtd = FALSE;
6435 norm = mono_type_normalize (t);
6438 requires_rebind = TRUE;
6442 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6444 if (requires_rebind) {
6445 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6446 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6452 * mono_type_get_object:
6453 * @domain: an app domain
6456 * Return an System.MonoType object representing the type @type.
6459 mono_type_get_object (MonoDomain *domain, MonoType *type)
6461 MonoType *norm_type;
6462 MonoReflectionType *res;
6463 MonoClass *klass = mono_class_from_mono_type (type);
6465 /*we must avoid using @type as it might have come
6466 * from a mono_metadata_type_dup and the caller
6467 * expects that is can be freed.
6468 * Using the right type from
6470 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6472 /* void is very common */
6473 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6474 return (MonoReflectionType*)domain->typeof_void;
6477 * If the vtable of the given class was already created, we can use
6478 * the MonoType from there and avoid all locking and hash table lookups.
6480 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6481 * that the resulting object is different.
6483 if (type == &klass->byval_arg && !klass->image->dynamic) {
6484 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6485 if (vtable && vtable->type)
6486 return vtable->type;
6489 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6490 mono_domain_lock (domain);
6491 if (!domain->type_hash)
6492 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6493 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6494 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6495 mono_domain_unlock (domain);
6496 mono_loader_unlock ();
6500 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6501 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6502 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6503 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6504 * artifact of how generics are encoded and should be transparent to managed code so we
6505 * need to weed out this diference when retrieving managed System.Type objects.
6507 norm_type = mono_type_normalize (type);
6508 if (norm_type != type) {
6509 res = mono_type_get_object (domain, norm_type);
6510 mono_g_hash_table_insert (domain->type_hash, type, res);
6511 mono_domain_unlock (domain);
6512 mono_loader_unlock ();
6516 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6517 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6520 if (!verify_safe_for_managed_space (type)) {
6521 mono_domain_unlock (domain);
6522 mono_loader_unlock ();
6523 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6526 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6527 gboolean is_type_done = TRUE;
6528 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6529 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6530 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6532 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6533 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6535 if (gparam->owner && gparam->owner->is_method) {
6536 MonoMethod *method = gparam->owner->owner.method;
6537 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6538 is_type_done = FALSE;
6539 } else if (gparam->owner && !gparam->owner->is_method) {
6540 MonoClass *klass = gparam->owner->owner.klass;
6541 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6542 is_type_done = FALSE;
6546 /* g_assert_not_reached (); */
6547 /* should this be considered an error condition? */
6548 if (is_type_done && !type->byref) {
6549 mono_domain_unlock (domain);
6550 mono_loader_unlock ();
6551 return mono_class_get_ref_info (klass);
6555 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6557 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6560 mono_g_hash_table_insert (domain->type_hash, type, res);
6562 if (type->type == MONO_TYPE_VOID)
6563 domain->typeof_void = (MonoObject*)res;
6565 mono_domain_unlock (domain);
6566 mono_loader_unlock ();
6571 * mono_method_get_object:
6572 * @domain: an app domain
6574 * @refclass: the reflected type (can be NULL)
6576 * Return an System.Reflection.MonoMethod object representing the method @method.
6578 MonoReflectionMethod*
6579 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6582 * We use the same C representation for methods and constructors, but the type
6583 * name in C# is different.
6585 static MonoClass *System_Reflection_MonoMethod = NULL;
6586 static MonoClass *System_Reflection_MonoCMethod = NULL;
6587 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6588 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6590 MonoReflectionMethod *ret;
6592 if (method->is_inflated) {
6593 MonoReflectionGenericMethod *gret;
6595 refclass = method->klass;
6596 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6598 if (!System_Reflection_MonoGenericCMethod)
6599 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6600 klass = System_Reflection_MonoGenericCMethod;
6602 if (!System_Reflection_MonoGenericMethod)
6603 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6604 klass = System_Reflection_MonoGenericMethod;
6606 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6607 gret->method.method = method;
6608 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6609 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6614 refclass = method->klass;
6616 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6617 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6618 if (!System_Reflection_MonoCMethod)
6619 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6620 klass = System_Reflection_MonoCMethod;
6623 if (!System_Reflection_MonoMethod)
6624 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6625 klass = System_Reflection_MonoMethod;
6627 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6628 ret->method = method;
6629 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6630 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6634 * mono_method_clear_object:
6636 * Clear the cached reflection objects for the dynamic method METHOD.
6639 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6642 g_assert (method->dynamic);
6644 klass = method->klass;
6646 clear_cached_object (domain, method, klass);
6647 klass = klass->parent;
6649 /* Added by mono_param_get_objects () */
6650 clear_cached_object (domain, &(method->signature), NULL);
6651 klass = method->klass;
6653 clear_cached_object (domain, &(method->signature), klass);
6654 klass = klass->parent;
6659 * mono_field_get_object:
6660 * @domain: an app domain
6664 * Return an System.Reflection.MonoField object representing the field @field
6667 MonoReflectionField*
6668 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6670 MonoReflectionField *res;
6671 static MonoClass *monofield_klass;
6673 CHECK_OBJECT (MonoReflectionField *, field, klass);
6674 if (!monofield_klass)
6675 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6676 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6679 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6681 if (is_field_on_inst (field)) {
6682 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6683 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6686 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6687 res->attrs = mono_field_get_flags (field);
6689 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6693 * mono_property_get_object:
6694 * @domain: an app domain
6696 * @property: a property
6698 * Return an System.Reflection.MonoProperty object representing the property @property
6701 MonoReflectionProperty*
6702 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6704 MonoReflectionProperty *res;
6705 static MonoClass *monoproperty_klass;
6707 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6708 if (!monoproperty_klass)
6709 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6710 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6712 res->property = property;
6713 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6717 * mono_event_get_object:
6718 * @domain: an app domain
6722 * Return an System.Reflection.MonoEvent object representing the event @event
6725 MonoReflectionEvent*
6726 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6728 MonoReflectionEvent *res;
6729 MonoReflectionMonoEvent *mono_event;
6730 static MonoClass *monoevent_klass;
6732 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6733 if (!monoevent_klass)
6734 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6735 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6736 mono_event->klass = klass;
6737 mono_event->event = event;
6738 res = (MonoReflectionEvent*)mono_event;
6739 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6743 * mono_get_reflection_missing_object:
6744 * @domain: Domain where the object lives
6746 * Returns the System.Reflection.Missing.Value singleton object
6747 * (of type System.Reflection.Missing).
6749 * Used as the value for ParameterInfo.DefaultValue when Optional
6753 mono_get_reflection_missing_object (MonoDomain *domain)
6756 static MonoClassField *missing_value_field = NULL;
6758 if (!missing_value_field) {
6759 MonoClass *missing_klass;
6760 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6761 mono_class_init (missing_klass);
6762 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6763 g_assert (missing_value_field);
6765 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6771 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6774 *dbnull = mono_get_dbnull_object (domain);
6779 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6781 if (!*reflection_missing)
6782 *reflection_missing = mono_get_reflection_missing_object (domain);
6783 return *reflection_missing;
6787 * mono_param_get_objects:
6788 * @domain: an app domain
6791 * Return an System.Reflection.ParameterInfo array object representing the parameters
6792 * in the method @method.
6795 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6797 static MonoClass *System_Reflection_ParameterInfo;
6798 static MonoClass *System_Reflection_ParameterInfo_array;
6799 MonoArray *res = NULL;
6800 MonoReflectionMethod *member = NULL;
6801 MonoReflectionParameter *param = NULL;
6802 char **names, **blobs = NULL;
6803 guint32 *types = NULL;
6804 MonoType *type = NULL;
6805 MonoObject *dbnull = NULL;
6806 MonoObject *missing = NULL;
6807 MonoMarshalSpec **mspecs;
6808 MonoMethodSignature *sig;
6809 MonoVTable *pinfo_vtable;
6812 if (!System_Reflection_ParameterInfo_array) {
6815 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6816 mono_memory_barrier ();
6817 System_Reflection_ParameterInfo = klass;
6819 klass = mono_array_class_get (klass, 1);
6820 mono_memory_barrier ();
6821 System_Reflection_ParameterInfo_array = klass;
6824 if (!mono_method_signature (method)->param_count)
6825 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6827 /* Note: the cache is based on the address of the signature into the method
6828 * since we already cache MethodInfos with the method as keys.
6830 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6832 sig = mono_method_signature (method);
6833 member = mono_method_get_object (domain, method, refclass);
6834 names = g_new (char *, sig->param_count);
6835 mono_method_get_param_names (method, (const char **) names);
6837 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6838 mono_method_get_marshal_info (method, mspecs);
6840 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6841 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6842 for (i = 0; i < sig->param_count; ++i) {
6843 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6844 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6845 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6846 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6847 param->PositionImpl = i;
6848 param->AttrsImpl = sig->params [i]->attrs;
6850 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6851 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6852 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6854 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6858 blobs = g_new0 (char *, sig->param_count);
6859 types = g_new0 (guint32, sig->param_count);
6860 get_default_param_value_blobs (method, blobs, types);
6863 /* Build MonoType for the type from the Constant Table */
6865 type = g_new0 (MonoType, 1);
6866 type->type = types [i];
6867 type->data.klass = NULL;
6868 if (types [i] == MONO_TYPE_CLASS)
6869 type->data.klass = mono_defaults.object_class;
6870 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6871 /* For enums, types [i] contains the base type */
6873 type->type = MONO_TYPE_VALUETYPE;
6874 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6876 type->data.klass = mono_class_from_mono_type (type);
6878 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6880 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6881 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6882 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6883 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6885 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6891 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6893 mono_array_setref (res, i, param);
6900 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6902 mono_metadata_free_marshal_spec (mspecs [i]);
6905 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6909 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6911 return mono_param_get_objects_internal (domain, method, NULL);
6915 * mono_method_body_get_object:
6916 * @domain: an app domain
6919 * Return an System.Reflection.MethodBody object representing the method @method.
6921 MonoReflectionMethodBody*
6922 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6924 static MonoClass *System_Reflection_MethodBody = NULL;
6925 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6926 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6927 MonoReflectionMethodBody *ret;
6928 MonoMethodHeader *header;
6930 guint32 method_rva, local_var_sig_token;
6932 unsigned char format, flags;
6935 if (!System_Reflection_MethodBody)
6936 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6937 if (!System_Reflection_LocalVariableInfo)
6938 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6939 if (!System_Reflection_ExceptionHandlingClause)
6940 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6942 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6944 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6945 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6946 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6947 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6950 image = method->klass->image;
6951 header = mono_method_get_header (method);
6953 if (!image->dynamic) {
6954 /* Obtain local vars signature token */
6955 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6956 ptr = mono_image_rva_map (image, method_rva);
6957 flags = *(const unsigned char *) ptr;
6958 format = flags & METHOD_HEADER_FORMAT_MASK;
6960 case METHOD_HEADER_TINY_FORMAT:
6961 local_var_sig_token = 0;
6963 case METHOD_HEADER_FAT_FORMAT:
6967 local_var_sig_token = read32 (ptr);
6970 g_assert_not_reached ();
6973 local_var_sig_token = 0; //FIXME
6975 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6977 ret->init_locals = header->init_locals;
6978 ret->max_stack = header->max_stack;
6979 ret->local_var_sig_token = local_var_sig_token;
6980 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6981 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6984 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6985 for (i = 0; i < header->num_locals; ++i) {
6986 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6987 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6988 info->is_pinned = header->locals [i]->pinned;
6989 info->local_index = i;
6990 mono_array_setref (ret->locals, i, info);
6994 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6995 for (i = 0; i < header->num_clauses; ++i) {
6996 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6997 MonoExceptionClause *clause = &header->clauses [i];
6999 info->flags = clause->flags;
7000 info->try_offset = clause->try_offset;
7001 info->try_length = clause->try_len;
7002 info->handler_offset = clause->handler_offset;
7003 info->handler_length = clause->handler_len;
7004 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7005 info->filter_offset = clause->data.filter_offset;
7006 else if (clause->data.catch_class)
7007 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7009 mono_array_setref (ret->clauses, i, info);
7012 mono_metadata_free_mh (header);
7013 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7018 * mono_get_dbnull_object:
7019 * @domain: Domain where the object lives
7021 * Returns the System.DBNull.Value singleton object
7023 * Used as the value for ParameterInfo.DefaultValue
7026 mono_get_dbnull_object (MonoDomain *domain)
7029 static MonoClassField *dbnull_value_field = NULL;
7031 if (!dbnull_value_field) {
7032 MonoClass *dbnull_klass;
7033 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7034 mono_class_init (dbnull_klass);
7035 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7036 g_assert (dbnull_value_field);
7038 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7044 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7046 guint32 param_index, i, lastp, crow = 0;
7047 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7050 MonoClass *klass = method->klass;
7051 MonoImage *image = klass->image;
7052 MonoMethodSignature *methodsig = mono_method_signature (method);
7054 MonoTableInfo *constt;
7055 MonoTableInfo *methodt;
7056 MonoTableInfo *paramt;
7058 if (!methodsig->param_count)
7061 mono_class_init (klass);
7063 if (klass->image->dynamic) {
7064 MonoReflectionMethodAux *aux;
7065 if (method->is_inflated)
7066 method = ((MonoMethodInflated*)method)->declaring;
7067 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7068 if (aux && aux->param_defaults) {
7069 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7070 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7075 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7076 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7077 constt = &image->tables [MONO_TABLE_CONSTANT];
7079 idx = mono_method_get_index (method) - 1;
7080 g_assert (idx != -1);
7082 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7083 if (idx + 1 < methodt->rows)
7084 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7086 lastp = paramt->rows + 1;
7088 for (i = param_index; i < lastp; ++i) {
7091 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7092 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7094 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7097 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7102 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7103 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7104 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7111 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7116 MonoType *basetype = type;
7121 klass = mono_class_from_mono_type (type);
7122 if (klass->valuetype) {
7123 object = mono_object_new (domain, klass);
7124 retval = ((gchar *) object + sizeof (MonoObject));
7125 if (klass->enumtype)
7126 basetype = mono_class_enum_basetype (klass);
7131 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7138 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7142 memset (assembly, 0, sizeof (MonoAssemblyName));
7144 assembly->culture = "";
7145 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7147 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7150 while (g_ascii_isspace (*p) || *p == ',') {
7159 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7161 assembly->major = strtoul (p, &s, 10);
7162 if (s == p || *s != '.')
7165 assembly->minor = strtoul (p, &s, 10);
7166 if (s == p || *s != '.')
7169 assembly->build = strtoul (p, &s, 10);
7170 if (s == p || *s != '.')
7173 assembly->revision = strtoul (p, &s, 10);
7177 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7179 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7180 assembly->culture = "";
7183 assembly->culture = p;
7184 while (*p && *p != ',') {
7188 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7190 if (strncmp (p, "null", 4) == 0) {
7195 while (*p && *p != ',') {
7198 len = (p - start + 1);
7199 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7200 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7201 g_strlcpy ((char*)assembly->public_key_token, start, len);
7204 while (*p && *p != ',')
7208 while (g_ascii_isspace (*p) || *p == ',') {
7222 * mono_reflection_parse_type:
7225 * Parse a type name as accepted by the GetType () method and output the info
7226 * extracted in the info structure.
7227 * the name param will be mangled, so, make a copy before passing it to this function.
7228 * The fields in info will be valid until the memory pointed to by name is valid.
7230 * See also mono_type_get_name () below.
7232 * Returns: 0 on parse error.
7235 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7236 MonoTypeNameParse *info)
7238 char *start, *p, *w, *temp, *last_point, *startn;
7239 int in_modifiers = 0;
7240 int isbyref = 0, rank, arity = 0, i;
7242 start = p = w = name;
7244 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7245 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7246 info->name = info->name_space = NULL;
7247 info->nested = NULL;
7248 info->modifiers = NULL;
7249 info->type_arguments = NULL;
7251 /* last_point separates the namespace from the name */
7254 while (*p == ' ') p++, start++, w++, name++;
7259 *p = 0; /* NULL terminate the name */
7261 info->nested = g_list_append (info->nested, startn);
7262 /* we have parsed the nesting namespace + name */
7266 info->name_space = start;
7268 info->name = last_point + 1;
7270 info->name_space = (char *)"";
7289 i = strtol (p, &temp, 10);
7306 info->name_space = start;
7308 info->name = last_point + 1;
7310 info->name_space = (char *)"";
7317 if (isbyref) /* only one level allowed by the spec */
7320 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7324 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7330 info->type_arguments = g_ptr_array_new ();
7331 for (i = 0; i < arity; i++) {
7332 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7333 gboolean fqname = FALSE;
7335 g_ptr_array_add (info->type_arguments, subinfo);
7342 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7345 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7346 if (fqname && (*p != ']')) {
7354 while (*p && (*p != ']'))
7362 if (g_ascii_isspace (*aname)) {
7369 !assembly_name_to_aname (&subinfo->assembly, aname))
7371 } else if (fqname && (*p == ']')) {
7375 if (i + 1 < arity) {
7395 else if (*p == '*') /* '*' means unknown lower bound */
7396 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7403 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7414 if (g_ascii_isspace (*p)) {
7421 return 0; /* missing assembly name */
7422 if (!assembly_name_to_aname (&info->assembly, p))
7428 if (info->assembly.name)
7431 // *w = 0; /* terminate class name */
7433 if (!info->name || !*info->name)
7437 /* add other consistency checks */
7442 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7444 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7448 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7450 gboolean type_resolve = FALSE;
7452 MonoImage *rootimage = image;
7454 if (info->assembly.name) {
7455 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7456 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7458 * This could happen in the AOT compiler case when the search hook is not
7461 assembly = image->assembly;
7463 /* then we must load the assembly ourselve - see #60439 */
7464 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7468 image = assembly->image;
7469 } else if (!image) {
7470 image = mono_defaults.corlib;
7473 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7474 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7475 image = mono_defaults.corlib;
7476 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7483 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7488 gboolean bounded = FALSE;
7491 image = mono_defaults.corlib;
7494 klass = mono_class_from_name_case (image, info->name_space, info->name);
7496 klass = mono_class_from_name (image, info->name_space, info->name);
7499 for (mod = info->nested; mod; mod = mod->next) {
7500 gpointer iter = NULL;
7504 mono_class_init (parent);
7506 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7508 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7511 if (strcmp (klass->name, mod->data) == 0)
7521 if (info->type_arguments) {
7522 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7523 MonoReflectionType *the_type;
7527 for (i = 0; i < info->type_arguments->len; i++) {
7528 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7530 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7531 if (!type_args [i]) {
7537 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7539 instance = mono_reflection_bind_generic_parameters (
7540 the_type, info->type_arguments->len, type_args);
7546 klass = mono_class_from_mono_type (instance);
7549 for (mod = info->modifiers; mod; mod = mod->next) {
7550 modval = GPOINTER_TO_UINT (mod->data);
7551 if (!modval) { /* byref: must be last modifier */
7552 return &klass->this_arg;
7553 } else if (modval == -1) {
7554 klass = mono_ptr_class_get (&klass->byval_arg);
7555 } else if (modval == -2) {
7557 } else { /* array rank */
7558 klass = mono_bounded_array_class_get (klass, modval, bounded);
7562 return &klass->byval_arg;
7566 * mono_reflection_get_type:
7567 * @image: a metadata context
7568 * @info: type description structure
7569 * @ignorecase: flag for case-insensitive string compares
7570 * @type_resolve: whenever type resolve was already tried
7572 * Build a MonoType from the type description in @info.
7577 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7578 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7582 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7584 MonoReflectionAssemblyBuilder *abuilder;
7588 g_assert (assembly->dynamic);
7589 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7591 /* Enumerate all modules */
7594 if (abuilder->modules) {
7595 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7596 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7597 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7603 if (!type && abuilder->loaded_modules) {
7604 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7605 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7606 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7616 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7619 MonoReflectionAssembly *assembly;
7623 if (image && image->dynamic)
7624 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7626 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7629 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7636 *type_resolve = TRUE;
7639 /* Reconstruct the type name */
7640 fullName = g_string_new ("");
7641 if (info->name_space && (info->name_space [0] != '\0'))
7642 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7644 g_string_printf (fullName, "%s", info->name);
7645 for (mod = info->nested; mod; mod = mod->next)
7646 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7648 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7650 if (assembly->assembly->dynamic)
7651 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7653 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7656 g_string_free (fullName, TRUE);
7661 mono_reflection_free_type_info (MonoTypeNameParse *info)
7663 g_list_free (info->modifiers);
7664 g_list_free (info->nested);
7666 if (info->type_arguments) {
7669 for (i = 0; i < info->type_arguments->len; i++) {
7670 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7672 mono_reflection_free_type_info (subinfo);
7673 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7677 g_ptr_array_free (info->type_arguments, TRUE);
7682 * mono_reflection_type_from_name:
7684 * @image: a metadata context (can be NULL).
7686 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7687 * it defaults to get the type from @image or, if @image is NULL or loading
7688 * from it fails, uses corlib.
7692 mono_reflection_type_from_name (char *name, MonoImage *image)
7694 MonoType *type = NULL;
7695 MonoTypeNameParse info;
7698 /* Make a copy since parse_type modifies its argument */
7699 tmp = g_strdup (name);
7701 /*g_print ("requested type %s\n", str);*/
7702 if (mono_reflection_parse_type (tmp, &info)) {
7703 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7707 mono_reflection_free_type_info (&info);
7712 * mono_reflection_get_token:
7714 * Return the metadata token of OBJ which should be an object
7715 * representing a metadata element.
7718 mono_reflection_get_token (MonoObject *obj)
7723 klass = obj->vtable->klass;
7725 if (strcmp (klass->name, "MethodBuilder") == 0) {
7726 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7728 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7729 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7730 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7732 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7733 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7734 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7736 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7737 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7738 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7739 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7740 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7741 } else if (strcmp (klass->name, "MonoType") == 0) {
7742 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7743 MonoClass *mc = mono_class_from_mono_type (type);
7744 if (!mono_class_init (mc))
7745 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7747 token = mc->type_token;
7748 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7749 strcmp (klass->name, "MonoMethod") == 0 ||
7750 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7751 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7752 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7753 if (m->method->is_inflated) {
7754 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7755 return inflated->declaring->token;
7757 token = m->method->token;
7759 } else if (strcmp (klass->name, "MonoField") == 0) {
7760 MonoReflectionField *f = (MonoReflectionField*)obj;
7762 if (is_field_on_inst (f->field)) {
7763 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7764 int field_index = f->field - dgclass->fields;
7767 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7768 obj = dgclass->field_objects [field_index];
7769 return mono_reflection_get_token (obj);
7771 token = mono_class_get_field_token (f->field);
7772 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7773 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7775 token = mono_class_get_property_token (p->property);
7776 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7777 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7779 token = mono_class_get_event_token (p->event);
7780 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7781 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7782 MonoClass *member_class = mono_object_class (p->MemberImpl);
7783 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7785 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7786 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7787 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7790 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7791 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7793 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7794 MonoException *ex = mono_get_exception_not_implemented (msg);
7796 mono_raise_exception (ex);
7803 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7805 int slen, type = t->type;
7806 MonoClass *tklass = t->data.klass;
7812 case MONO_TYPE_BOOLEAN: {
7813 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7818 case MONO_TYPE_CHAR:
7820 case MONO_TYPE_I2: {
7821 guint16 *val = g_malloc (sizeof (guint16));
7826 #if SIZEOF_VOID_P == 4
7832 case MONO_TYPE_I4: {
7833 guint32 *val = g_malloc (sizeof (guint32));
7838 #if SIZEOF_VOID_P == 8
7839 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7843 case MONO_TYPE_I8: {
7844 guint64 *val = g_malloc (sizeof (guint64));
7849 case MONO_TYPE_R8: {
7850 double *val = g_malloc (sizeof (double));
7855 case MONO_TYPE_VALUETYPE:
7856 if (t->data.klass->enumtype) {
7857 type = mono_class_enum_basetype (t->data.klass)->type;
7860 MonoClass *k = t->data.klass;
7862 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7863 guint64 *val = g_malloc (sizeof (guint64));
7869 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7872 case MONO_TYPE_STRING:
7873 if (*p == (char)0xFF) {
7877 slen = mono_metadata_decode_value (p, &p);
7879 return mono_string_new_len (mono_domain_get (), p, slen);
7880 case MONO_TYPE_CLASS: {
7883 if (*p == (char)0xFF) {
7888 slen = mono_metadata_decode_value (p, &p);
7889 n = g_memdup (p, slen + 1);
7891 t = mono_reflection_type_from_name (n, image);
7893 g_warning ("Cannot load type '%s'", n);
7897 return mono_type_get_object (mono_domain_get (), t);
7901 case MONO_TYPE_OBJECT: {
7904 MonoClass *subc = NULL;
7909 } else if (subt == 0x0E) {
7910 type = MONO_TYPE_STRING;
7912 } else if (subt == 0x1D) {
7913 MonoType simple_type = {{0}};
7918 /* See Partition II, Appendix B3 */
7919 etype = MONO_TYPE_OBJECT;
7920 type = MONO_TYPE_SZARRAY;
7921 simple_type.type = etype;
7922 tklass = mono_class_from_mono_type (&simple_type);
7924 } else if (subt == 0x55) {
7927 slen = mono_metadata_decode_value (p, &p);
7928 n = g_memdup (p, slen + 1);
7930 t = mono_reflection_type_from_name (n, image);
7932 g_error ("Cannot load type '%s'", n);
7935 subc = mono_class_from_mono_type (t);
7936 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7937 MonoType simple_type = {{0}};
7938 simple_type.type = subt;
7939 subc = mono_class_from_mono_type (&simple_type);
7941 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7943 val = load_cattr_value (image, &subc->byval_arg, p, end);
7944 obj = mono_object_new (mono_domain_get (), subc);
7945 g_assert (!subc->has_references);
7946 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7950 case MONO_TYPE_SZARRAY: {
7952 guint32 i, alen, basetype;
7955 if (alen == 0xffffffff) {
7959 arr = mono_array_new (mono_domain_get(), tklass, alen);
7960 basetype = tklass->byval_arg.type;
7961 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7962 basetype = mono_class_enum_basetype (tklass)->type;
7967 case MONO_TYPE_BOOLEAN:
7968 for (i = 0; i < alen; i++) {
7969 MonoBoolean val = *p++;
7970 mono_array_set (arr, MonoBoolean, i, val);
7973 case MONO_TYPE_CHAR:
7976 for (i = 0; i < alen; i++) {
7977 guint16 val = read16 (p);
7978 mono_array_set (arr, guint16, i, val);
7985 for (i = 0; i < alen; i++) {
7986 guint32 val = read32 (p);
7987 mono_array_set (arr, guint32, i, val);
7992 for (i = 0; i < alen; i++) {
7995 mono_array_set (arr, double, i, val);
8001 for (i = 0; i < alen; i++) {
8002 guint64 val = read64 (p);
8003 mono_array_set (arr, guint64, i, val);
8007 case MONO_TYPE_CLASS:
8008 case MONO_TYPE_OBJECT:
8009 case MONO_TYPE_STRING:
8010 for (i = 0; i < alen; i++) {
8011 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8012 mono_array_setref (arr, i, item);
8016 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8022 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8028 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8030 static MonoClass *klass;
8031 static MonoMethod *ctor;
8033 void *params [2], *unboxed;
8036 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8038 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8040 params [0] = mono_type_get_object (mono_domain_get (), t);
8042 retval = mono_object_new (mono_domain_get (), klass);
8043 unboxed = mono_object_unbox (retval);
8044 mono_runtime_invoke (ctor, unboxed, params, NULL);
8050 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8052 static MonoClass *klass;
8053 static MonoMethod *ctor;
8055 void *unboxed, *params [2];
8058 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8060 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8063 params [1] = typedarg;
8064 retval = mono_object_new (mono_domain_get (), klass);
8065 unboxed = mono_object_unbox (retval);
8066 mono_runtime_invoke (ctor, unboxed, params, NULL);
8072 type_is_reference (MonoType *type)
8074 switch (type->type) {
8075 case MONO_TYPE_BOOLEAN:
8076 case MONO_TYPE_CHAR:
8089 case MONO_TYPE_VALUETYPE:
8097 free_param_data (MonoMethodSignature *sig, void **params) {
8099 for (i = 0; i < sig->param_count; ++i) {
8100 if (!type_is_reference (sig->params [i]))
8101 g_free (params [i]);
8106 * Find the field index in the metadata FieldDef table.
8109 find_field_index (MonoClass *klass, MonoClassField *field) {
8112 for (i = 0; i < klass->field.count; ++i) {
8113 if (field == &klass->fields [i])
8114 return klass->field.first + 1 + i;
8120 * Find the property index in the metadata Property table.
8123 find_property_index (MonoClass *klass, MonoProperty *property) {
8126 for (i = 0; i < klass->ext->property.count; ++i) {
8127 if (property == &klass->ext->properties [i])
8128 return klass->ext->property.first + 1 + i;
8134 * Find the event index in the metadata Event table.
8137 find_event_index (MonoClass *klass, MonoEvent *event) {
8140 for (i = 0; i < klass->ext->event.count; ++i) {
8141 if (event == &klass->ext->events [i])
8142 return klass->ext->event.first + 1 + i;
8148 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8150 const char *p = (const char*)data;
8152 guint32 i, j, num_named;
8154 void *params_buf [32];
8156 MonoMethodSignature *sig;
8158 mono_class_init (method->klass);
8160 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8164 attr = mono_object_new (mono_domain_get (), method->klass);
8165 mono_runtime_invoke (method, attr, NULL, NULL);
8169 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8172 /*g_print ("got attr %s\n", method->klass->name);*/
8174 sig = mono_method_signature (method);
8175 if (sig->param_count < 32)
8176 params = params_buf;
8178 /* Allocate using GC so it gets GC tracking */
8179 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8183 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8184 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8188 attr = mono_object_new (mono_domain_get (), method->klass);
8189 mono_runtime_invoke (method, attr, params, NULL);
8190 free_param_data (method->signature, params);
8191 num_named = read16 (named);
8193 for (j = 0; j < num_named; j++) {
8195 char *name, named_type, data_type;
8196 named_type = *named++;
8197 data_type = *named++; /* type of data */
8198 if (data_type == MONO_TYPE_SZARRAY)
8199 data_type = *named++;
8200 if (data_type == MONO_TYPE_ENUM) {
8203 type_len = mono_metadata_decode_blob_size (named, &named);
8204 type_name = g_malloc (type_len + 1);
8205 memcpy (type_name, named, type_len);
8206 type_name [type_len] = 0;
8208 /* FIXME: lookup the type and check type consistency */
8211 name_len = mono_metadata_decode_blob_size (named, &named);
8212 name = g_malloc (name_len + 1);
8213 memcpy (name, named, name_len);
8214 name [name_len] = 0;
8216 if (named_type == 0x53) {
8217 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8218 void *val = load_cattr_value (image, field->type, named, &named);
8219 mono_field_set_value (attr, field, val);
8220 if (!type_is_reference (field->type))
8222 } else if (named_type == 0x54) {
8225 MonoType *prop_type;
8227 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8228 /* can we have more that 1 arg in a custom attr named property? */
8229 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8230 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8231 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8232 mono_property_set_value (prop, attr, pparams, NULL);
8233 if (!type_is_reference (prop_type))
8234 g_free (pparams [0]);
8239 if (params != params_buf)
8240 mono_gc_free_fixed (params);
8246 * mono_reflection_create_custom_attr_data_args:
8248 * Create an array of typed and named arguments from the cattr blob given by DATA.
8249 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8250 * NAMED_ARG_INFO will contain information about the named arguments.
8253 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)
8255 MonoArray *typedargs, *namedargs;
8256 MonoClass *attrklass;
8258 const char *p = (const char*)data;
8260 guint32 i, j, num_named;
8261 CattrNamedArg *arginfo = NULL;
8263 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8266 mono_class_init (method->klass);
8270 *named_arg_info = NULL;
8272 domain = mono_domain_get ();
8274 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8277 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8281 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8285 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8286 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8287 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8288 mono_array_setref (typedargs, i, obj);
8290 if (!type_is_reference (mono_method_signature (method)->params [i]))
8295 num_named = read16 (named);
8296 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8298 attrklass = method->klass;
8300 arginfo = g_new0 (CattrNamedArg, num_named);
8301 *named_arg_info = arginfo;
8303 for (j = 0; j < num_named; j++) {
8305 char *name, named_type, data_type;
8306 named_type = *named++;
8307 data_type = *named++; /* type of data */
8308 if (data_type == MONO_TYPE_SZARRAY)
8309 data_type = *named++;
8310 if (data_type == MONO_TYPE_ENUM) {
8313 type_len = mono_metadata_decode_blob_size (named, &named);
8314 type_name = g_malloc (type_len + 1);
8315 memcpy (type_name, named, type_len);
8316 type_name [type_len] = 0;
8318 /* FIXME: lookup the type and check type consistency */
8321 name_len = mono_metadata_decode_blob_size (named, &named);
8322 name = g_malloc (name_len + 1);
8323 memcpy (name, named, name_len);
8324 name [name_len] = 0;
8326 if (named_type == 0x53) {
8328 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8331 arginfo [j].type = field->type;
8332 arginfo [j].field = field;
8334 val = load_cattr_value (image, field->type, named, &named);
8335 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8336 mono_array_setref (namedargs, j, obj);
8337 if (!type_is_reference (field->type))
8339 } else if (named_type == 0x54) {
8341 MonoType *prop_type;
8342 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8345 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8346 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8348 arginfo [j].type = prop_type;
8349 arginfo [j].prop = prop;
8351 val = load_cattr_value (image, prop_type, named, &named);
8352 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8353 mono_array_setref (namedargs, j, obj);
8354 if (!type_is_reference (prop_type))
8360 *typed_args = typedargs;
8361 *named_args = namedargs;
8365 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8368 MonoArray *typedargs, *namedargs;
8371 CattrNamedArg *arginfo;
8380 image = assembly->assembly->image;
8381 method = ref_method->method;
8382 domain = mono_object_domain (ref_method);
8384 if (!mono_class_init (method->klass))
8385 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8387 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8388 if (mono_loader_get_last_error ())
8389 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8391 if (!typedargs || !namedargs)
8394 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8395 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8396 MonoObject *typedarg;
8398 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8399 mono_array_setref (typedargs, i, typedarg);
8402 for (i = 0; i < mono_array_length (namedargs); ++i) {
8403 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8404 MonoObject *typedarg, *namedarg, *minfo;
8406 if (arginfo [i].prop)
8407 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8409 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8411 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8412 namedarg = create_cattr_named_arg (minfo, typedarg);
8414 mono_array_setref (namedargs, i, namedarg);
8417 *ctor_args = typedargs;
8418 *named_args = namedargs;
8422 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8424 static MonoMethod *ctor;
8429 g_assert (image->assembly);
8432 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8434 domain = mono_domain_get ();
8435 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8436 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8437 params [1] = mono_assembly_get_object (domain, image->assembly);
8438 params [2] = (gpointer)&cattr->data;
8439 params [3] = &cattr->data_size;
8440 mono_runtime_invoke (ctor, attr, params, NULL);
8445 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8451 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8452 for (i = 0; i < cinfo->num_attrs; ++i) {
8453 if (!cinfo->attrs [i].ctor)
8454 /* The cattr type is not finished yet */
8455 /* We should include the type name but cinfo doesn't contain it */
8456 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8457 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8458 mono_array_setref (result, i, attr);
8464 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8471 for (i = 0; i < cinfo->num_attrs; ++i) {
8472 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8476 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8478 for (i = 0; i < cinfo->num_attrs; ++i) {
8479 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8480 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8481 mono_array_setref (result, n, attr);
8489 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8495 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8496 for (i = 0; i < cinfo->num_attrs; ++i) {
8497 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8498 mono_array_setref (result, i, attr);
8504 * mono_custom_attrs_from_index:
8506 * Returns: NULL if no attributes are found or if a loading error occurs.
8509 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8511 guint32 mtoken, i, len;
8512 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8514 MonoCustomAttrInfo *ainfo;
8515 GList *tmp, *list = NULL;
8518 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8520 i = mono_metadata_custom_attrs_from_index (image, idx);
8524 while (i < ca->rows) {
8525 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8527 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8530 len = g_list_length (list);
8533 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8534 ainfo->num_attrs = len;
8535 ainfo->image = image;
8536 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8537 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8538 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8539 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8540 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8541 mtoken |= MONO_TOKEN_METHOD_DEF;
8543 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8544 mtoken |= MONO_TOKEN_MEMBER_REF;
8547 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8550 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8551 if (!ainfo->attrs [i].ctor) {
8552 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8558 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8559 /*FIXME raising an exception here doesn't make any sense*/
8560 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8565 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8566 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8567 ainfo->attrs [i].data = (guchar*)data;
8575 mono_custom_attrs_from_method (MonoMethod *method)
8580 * An instantiated method has the same cattrs as the generic method definition.
8582 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8583 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8585 if (method->is_inflated)
8586 method = ((MonoMethodInflated *) method)->declaring;
8588 if (method->dynamic || method->klass->image->dynamic)
8589 return lookup_custom_attr (method->klass->image, method);
8592 /* Synthetic methods */
8595 idx = mono_method_get_index (method);
8596 idx <<= MONO_CUSTOM_ATTR_BITS;
8597 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8598 return mono_custom_attrs_from_index (method->klass->image, idx);
8602 mono_custom_attrs_from_class (MonoClass *klass)
8606 if (klass->generic_class)
8607 klass = klass->generic_class->container_class;
8609 if (klass->image->dynamic)
8610 return lookup_custom_attr (klass->image, klass);
8612 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8613 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8614 idx <<= MONO_CUSTOM_ATTR_BITS;
8615 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8617 idx = mono_metadata_token_index (klass->type_token);
8618 idx <<= MONO_CUSTOM_ATTR_BITS;
8619 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8621 return mono_custom_attrs_from_index (klass->image, idx);
8625 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8629 if (assembly->image->dynamic)
8630 return lookup_custom_attr (assembly->image, assembly);
8631 idx = 1; /* there is only one assembly */
8632 idx <<= MONO_CUSTOM_ATTR_BITS;
8633 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8634 return mono_custom_attrs_from_index (assembly->image, idx);
8637 static MonoCustomAttrInfo*
8638 mono_custom_attrs_from_module (MonoImage *image)
8643 return lookup_custom_attr (image, image);
8644 idx = 1; /* there is only one module */
8645 idx <<= MONO_CUSTOM_ATTR_BITS;
8646 idx |= MONO_CUSTOM_ATTR_MODULE;
8647 return mono_custom_attrs_from_index (image, idx);
8651 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8655 if (klass->image->dynamic) {
8656 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8657 return lookup_custom_attr (klass->image, property);
8659 idx = find_property_index (klass, property);
8660 idx <<= MONO_CUSTOM_ATTR_BITS;
8661 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8662 return mono_custom_attrs_from_index (klass->image, idx);
8666 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8670 if (klass->image->dynamic) {
8671 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8672 return lookup_custom_attr (klass->image, event);
8674 idx = find_event_index (klass, event);
8675 idx <<= MONO_CUSTOM_ATTR_BITS;
8676 idx |= MONO_CUSTOM_ATTR_EVENT;
8677 return mono_custom_attrs_from_index (klass->image, idx);
8681 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8684 if (klass->image->dynamic) {
8685 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8686 return lookup_custom_attr (klass->image, field);
8688 idx = find_field_index (klass, field);
8689 idx <<= MONO_CUSTOM_ATTR_BITS;
8690 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8691 return mono_custom_attrs_from_index (klass->image, idx);
8695 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8698 guint32 i, idx, method_index;
8699 guint32 param_list, param_last, param_pos, found;
8701 MonoReflectionMethodAux *aux;
8704 * An instantiated method has the same cattrs as the generic method definition.
8706 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8707 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8709 if (method->is_inflated)
8710 method = ((MonoMethodInflated *) method)->declaring;
8712 if (method->klass->image->dynamic) {
8713 MonoCustomAttrInfo *res, *ainfo;
8716 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8717 if (!aux || !aux->param_cattr)
8720 /* Need to copy since it will be freed later */
8721 ainfo = aux->param_cattr [param];
8724 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8725 res = g_malloc0 (size);
8726 memcpy (res, ainfo, size);
8730 image = method->klass->image;
8731 method_index = mono_method_get_index (method);
8734 ca = &image->tables [MONO_TABLE_METHOD];
8736 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8737 if (method_index == ca->rows) {
8738 ca = &image->tables [MONO_TABLE_PARAM];
8739 param_last = ca->rows + 1;
8741 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8742 ca = &image->tables [MONO_TABLE_PARAM];
8745 for (i = param_list; i < param_last; ++i) {
8746 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8747 if (param_pos == param) {
8755 idx <<= MONO_CUSTOM_ATTR_BITS;
8756 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8757 return mono_custom_attrs_from_index (image, idx);
8761 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8765 for (i = 0; i < ainfo->num_attrs; ++i) {
8766 klass = ainfo->attrs [i].ctor->klass;
8767 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8774 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8781 for (i = 0; i < ainfo->num_attrs; ++i) {
8782 klass = ainfo->attrs [i].ctor->klass;
8783 if (mono_class_has_parent (klass, attr_klass)) {
8788 if (attr_index == -1)
8791 attrs = mono_custom_attrs_construct (ainfo);
8793 return mono_array_get (attrs, MonoObject*, attr_index);
8799 * mono_reflection_get_custom_attrs_info:
8800 * @obj: a reflection object handle
8802 * Return the custom attribute info for attributes defined for the
8803 * reflection handle @obj. The objects.
8805 * FIXME this function leaks like a sieve for SRE objects.
8808 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8811 MonoCustomAttrInfo *cinfo = NULL;
8813 klass = obj->vtable->klass;
8814 if (klass == mono_defaults.monotype_class) {
8815 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8816 klass = mono_class_from_mono_type (type);
8817 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8818 cinfo = mono_custom_attrs_from_class (klass);
8819 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8820 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8821 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8822 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8823 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8824 cinfo = mono_custom_attrs_from_module (module->image);
8825 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8826 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8827 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8828 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8829 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8830 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8831 } else if (strcmp ("MonoField", klass->name) == 0) {
8832 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8833 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8834 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8835 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8836 cinfo = mono_custom_attrs_from_method (rmethod->method);
8837 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8838 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8839 cinfo = mono_custom_attrs_from_method (rmethod->method);
8840 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8841 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8842 MonoClass *member_class = mono_object_class (param->MemberImpl);
8843 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8844 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8845 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8846 } else if (is_sr_mono_property (member_class)) {
8847 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8849 if (!(method = prop->property->get))
8850 method = prop->property->set;
8853 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8855 #ifndef DISABLE_REFLECTION_EMIT
8856 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8857 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8858 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8859 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8860 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8861 MonoMethod *method = NULL;
8862 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8863 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8864 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8865 method = ((MonoReflectionMethod *)c->cb)->method;
8867 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));
8869 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8873 char *type_name = mono_type_get_full_name (member_class);
8874 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8875 MonoException *ex = mono_get_exception_not_supported (msg);
8878 mono_raise_exception (ex);
8880 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8881 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8882 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8883 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8884 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8885 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8886 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8887 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8888 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8889 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8890 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8891 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8892 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8893 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8894 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8895 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8896 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8897 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8898 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8899 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8900 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8901 } else { /* handle other types here... */
8902 g_error ("get custom attrs not yet supported for %s", klass->name);
8909 * mono_reflection_get_custom_attrs_by_type:
8910 * @obj: a reflection object handle
8912 * Return an array with all the custom attributes defined of the
8913 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8914 * of that type are returned. The objects are fully build. Return NULL if a loading error
8918 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8921 MonoCustomAttrInfo *cinfo;
8923 cinfo = mono_reflection_get_custom_attrs_info (obj);
8926 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8928 result = mono_custom_attrs_construct (cinfo);
8930 mono_custom_attrs_free (cinfo);
8932 if (mono_loader_get_last_error ())
8934 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8941 * mono_reflection_get_custom_attrs:
8942 * @obj: a reflection object handle
8944 * Return an array with all the custom attributes defined of the
8945 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8949 mono_reflection_get_custom_attrs (MonoObject *obj)
8951 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8955 * mono_reflection_get_custom_attrs_data:
8956 * @obj: a reflection obj handle
8958 * Returns an array of System.Reflection.CustomAttributeData,
8959 * which include information about attributes reflected on
8960 * types loaded using the Reflection Only methods
8963 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8966 MonoCustomAttrInfo *cinfo;
8968 cinfo = mono_reflection_get_custom_attrs_info (obj);
8970 result = mono_custom_attrs_data_construct (cinfo);
8972 mono_custom_attrs_free (cinfo);
8974 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8979 static MonoReflectionType*
8980 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8982 static MonoMethod *method_get_underlying_system_type = NULL;
8983 MonoMethod *usertype_method;
8985 if (!method_get_underlying_system_type)
8986 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8987 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8988 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8993 is_corlib_type (MonoClass *class)
8995 return class->image == mono_defaults.corlib;
8998 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8999 static MonoClass *cached_class; \
9001 return cached_class == _class; \
9002 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9003 cached_class = _class; \
9010 #ifndef DISABLE_REFLECTION_EMIT
9012 is_sre_array (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9018 is_sre_byref (MonoClass *class)
9020 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9024 is_sre_pointer (MonoClass *class)
9026 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9030 is_sre_generic_instance (MonoClass *class)
9032 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9036 is_sre_type_builder (MonoClass *class)
9038 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9042 is_sre_method_builder (MonoClass *class)
9044 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9048 is_sre_ctor_builder (MonoClass *class)
9050 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9054 is_sre_field_builder (MonoClass *class)
9056 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9060 is_sre_method_on_tb_inst (MonoClass *class)
9062 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9066 is_sre_ctor_on_tb_inst (MonoClass *class)
9068 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9072 mono_reflection_type_get_handle (MonoReflectionType* ref)
9080 if (is_usertype (ref)) {
9081 ref = mono_reflection_type_get_underlying_system_type (ref);
9082 if (ref == NULL || is_usertype (ref))
9088 class = mono_object_class (ref);
9090 if (is_sre_array (class)) {
9092 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9093 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9095 if (sre_array->rank == 0) //single dimentional array
9096 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9098 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9099 sre_array->type.type = res;
9101 } else if (is_sre_byref (class)) {
9103 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9104 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9106 res = &mono_class_from_mono_type (base)->this_arg;
9107 sre_byref->type.type = res;
9109 } else if (is_sre_pointer (class)) {
9111 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9112 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9114 res = &mono_ptr_class_get (base)->byval_arg;
9115 sre_pointer->type.type = res;
9117 } else if (is_sre_generic_instance (class)) {
9118 MonoType *res, **types;
9119 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9122 count = mono_array_length (gclass->type_arguments);
9123 types = g_new0 (MonoType*, count);
9124 for (i = 0; i < count; ++i) {
9125 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9126 types [i] = mono_reflection_type_get_handle (t);
9133 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9136 gclass->type.type = res;
9140 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9147 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9149 mono_reflection_type_get_handle (type);
9153 mono_reflection_register_with_runtime (MonoReflectionType *type)
9155 MonoType *res = mono_reflection_type_get_handle (type);
9156 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9160 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9162 class = mono_class_from_mono_type (res);
9164 mono_loader_lock (); /*same locking as mono_type_get_object*/
9165 mono_domain_lock (domain);
9167 if (!class->image->dynamic) {
9168 mono_class_setup_supertypes (class);
9170 if (!domain->type_hash)
9171 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9172 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9173 mono_g_hash_table_insert (domain->type_hash, res, type);
9175 mono_domain_unlock (domain);
9176 mono_loader_unlock ();
9180 * LOCKING: Assumes the loader lock is held.
9182 static MonoMethodSignature*
9183 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9184 MonoMethodSignature *sig;
9187 count = parameters? mono_array_length (parameters): 0;
9189 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9190 sig->param_count = count;
9191 sig->sentinelpos = -1; /* FIXME */
9192 for (i = 0; i < count; ++i)
9193 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9198 * LOCKING: Assumes the loader lock is held.
9200 static MonoMethodSignature*
9201 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9202 MonoMethodSignature *sig;
9204 sig = parameters_to_signature (image, ctor->parameters);
9205 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9206 sig->ret = &mono_defaults.void_class->byval_arg;
9211 * LOCKING: Assumes the loader lock is held.
9213 static MonoMethodSignature*
9214 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9215 MonoMethodSignature *sig;
9217 sig = parameters_to_signature (image, method->parameters);
9218 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9219 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9220 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9224 static MonoMethodSignature*
9225 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9226 MonoMethodSignature *sig;
9228 sig = parameters_to_signature (NULL, method->parameters);
9229 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9230 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9231 sig->generic_param_count = 0;
9236 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9238 MonoClass *klass = mono_object_class (prop);
9239 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9240 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9241 *name = mono_string_to_utf8 (pb->name);
9242 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9244 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9245 *name = g_strdup (p->property->name);
9246 if (p->property->get)
9247 *type = mono_method_signature (p->property->get)->ret;
9249 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9254 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9256 MonoClass *klass = mono_object_class (field);
9257 if (strcmp (klass->name, "FieldBuilder") == 0) {
9258 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9259 *name = mono_string_to_utf8 (fb->name);
9260 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9262 MonoReflectionField *f = (MonoReflectionField *)field;
9263 *name = g_strdup (mono_field_get_name (f->field));
9264 *type = f->field->type;
9268 #else /* DISABLE_REFLECTION_EMIT */
9271 mono_reflection_register_with_runtime (MonoReflectionType *type)
9277 is_sre_type_builder (MonoClass *class)
9283 is_sre_generic_instance (MonoClass *class)
9288 #endif /* !DISABLE_REFLECTION_EMIT */
9292 is_sr_mono_field (MonoClass *class)
9294 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9298 is_sr_mono_property (MonoClass *class)
9300 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9304 is_sr_mono_method (MonoClass *class)
9306 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9310 is_sr_mono_cmethod (MonoClass *class)
9312 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9316 is_sr_mono_generic_method (MonoClass *class)
9318 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9322 is_sr_mono_generic_cmethod (MonoClass *class)
9324 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9328 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9330 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9334 is_usertype (MonoReflectionType *ref)
9336 MonoClass *class = mono_object_class (ref);
9337 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9340 static MonoReflectionType*
9341 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9343 if (!type || type->type)
9346 if (is_usertype (type)) {
9347 type = mono_reflection_type_get_underlying_system_type (type);
9348 if (is_usertype (type))
9349 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9355 * Encode a value in a custom attribute stream of bytes.
9356 * The value to encode is either supplied as an object in argument val
9357 * (valuetypes are boxed), or as a pointer to the data in the
9359 * @type represents the type of the value
9360 * @buffer is the start of the buffer
9361 * @p the current position in the buffer
9362 * @buflen contains the size of the buffer and is used to return the new buffer size
9363 * if this needs to be realloced.
9364 * @retbuffer and @retp return the start and the position of the buffer
9367 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9369 MonoTypeEnum simple_type;
9371 if ((p-buffer) + 10 >= *buflen) {
9374 newbuf = g_realloc (buffer, *buflen);
9375 p = newbuf + (p-buffer);
9379 argval = ((char*)arg + sizeof (MonoObject));
9380 simple_type = type->type;
9382 switch (simple_type) {
9383 case MONO_TYPE_BOOLEAN:
9388 case MONO_TYPE_CHAR:
9391 swap_with_size (p, argval, 2, 1);
9397 swap_with_size (p, argval, 4, 1);
9401 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9411 swap_with_size (p, argval, 8, 1);
9417 swap_with_size (p, argval, 8, 1);
9420 case MONO_TYPE_VALUETYPE:
9421 if (type->data.klass->enumtype) {
9422 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9425 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9428 case MONO_TYPE_STRING: {
9435 str = mono_string_to_utf8 ((MonoString*)arg);
9436 slen = strlen (str);
9437 if ((p-buffer) + 10 + slen >= *buflen) {
9441 newbuf = g_realloc (buffer, *buflen);
9442 p = newbuf + (p-buffer);
9445 mono_metadata_encode_value (slen, p, &p);
9446 memcpy (p, str, slen);
9451 case MONO_TYPE_CLASS: {
9459 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9460 slen = strlen (str);
9461 if ((p-buffer) + 10 + slen >= *buflen) {
9465 newbuf = g_realloc (buffer, *buflen);
9466 p = newbuf + (p-buffer);
9469 mono_metadata_encode_value (slen, p, &p);
9470 memcpy (p, str, slen);
9475 case MONO_TYPE_SZARRAY: {
9477 MonoClass *eclass, *arg_eclass;
9480 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9483 len = mono_array_length ((MonoArray*)arg);
9485 *p++ = (len >> 8) & 0xff;
9486 *p++ = (len >> 16) & 0xff;
9487 *p++ = (len >> 24) & 0xff;
9489 *retbuffer = buffer;
9490 eclass = type->data.klass;
9491 arg_eclass = mono_object_class (arg)->element_class;
9494 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9495 eclass = mono_defaults.object_class;
9497 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9498 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9499 int elsize = mono_class_array_element_size (arg_eclass);
9500 for (i = 0; i < len; ++i) {
9501 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9504 } else if (eclass->valuetype && arg_eclass->valuetype) {
9505 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9506 int elsize = mono_class_array_element_size (eclass);
9507 for (i = 0; i < len; ++i) {
9508 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9512 for (i = 0; i < len; ++i) {
9513 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9518 case MONO_TYPE_OBJECT: {
9524 * The parameter type is 'object' but the type of the actual
9525 * argument is not. So we have to add type information to the blob
9526 * too. This is completely undocumented in the spec.
9530 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9535 klass = mono_object_class (arg);
9537 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9540 } else if (klass->enumtype) {
9542 } else if (klass == mono_defaults.string_class) {
9543 simple_type = MONO_TYPE_STRING;
9546 } else if (klass->rank == 1) {
9548 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9549 /* See Partition II, Appendix B3 */
9552 *p++ = klass->element_class->byval_arg.type;
9553 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9555 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9556 *p++ = simple_type = klass->byval_arg.type;
9559 g_error ("unhandled type in custom attr");
9561 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9562 slen = strlen (str);
9563 if ((p-buffer) + 10 + slen >= *buflen) {
9567 newbuf = g_realloc (buffer, *buflen);
9568 p = newbuf + (p-buffer);
9571 mono_metadata_encode_value (slen, p, &p);
9572 memcpy (p, str, slen);
9575 simple_type = mono_class_enum_basetype (klass)->type;
9579 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9582 *retbuffer = buffer;
9586 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9588 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9589 char *str = type_get_qualified_name (type, NULL);
9590 int slen = strlen (str);
9594 * This seems to be optional...
9597 mono_metadata_encode_value (slen, p, &p);
9598 memcpy (p, str, slen);
9601 } else if (type->type == MONO_TYPE_OBJECT) {
9603 } else if (type->type == MONO_TYPE_CLASS) {
9604 /* it should be a type: encode_cattr_value () has the check */
9607 mono_metadata_encode_value (type->type, p, &p);
9608 if (type->type == MONO_TYPE_SZARRAY)
9609 /* See the examples in Partition VI, Annex B */
9610 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9616 #ifndef DISABLE_REFLECTION_EMIT
9618 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9621 /* Preallocate a large enough buffer */
9622 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9623 char *str = type_get_qualified_name (type, NULL);
9626 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9627 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9633 len += strlen (name);
9635 if ((p-buffer) + 20 + len >= *buflen) {
9639 newbuf = g_realloc (buffer, *buflen);
9640 p = newbuf + (p-buffer);
9644 encode_field_or_prop_type (type, p, &p);
9646 len = strlen (name);
9647 mono_metadata_encode_value (len, p, &p);
9648 memcpy (p, name, len);
9650 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9652 *retbuffer = buffer;
9656 * mono_reflection_get_custom_attrs_blob:
9657 * @ctor: custom attribute constructor
9658 * @ctorArgs: arguments o the constructor
9664 * Creates the blob of data that needs to be saved in the metadata and that represents
9665 * the custom attributed described by @ctor, @ctorArgs etc.
9666 * Returns: a Byte array representing the blob of data.
9669 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9672 MonoMethodSignature *sig;
9677 MONO_ARCH_SAVE_REGS;
9679 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9680 /* sig is freed later so allocate it in the heap */
9681 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9683 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9686 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9688 p = buffer = g_malloc (buflen);
9689 /* write the prolog */
9692 for (i = 0; i < sig->param_count; ++i) {
9693 arg = mono_array_get (ctorArgs, MonoObject*, i);
9694 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9698 i += mono_array_length (properties);
9700 i += mono_array_length (fields);
9702 *p++ = (i >> 8) & 0xff;
9705 for (i = 0; i < mono_array_length (properties); ++i) {
9709 prop = mono_array_get (properties, gpointer, i);
9710 get_prop_name_and_type (prop, &pname, &ptype);
9711 *p++ = 0x54; /* PROPERTY signature */
9712 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9719 for (i = 0; i < mono_array_length (fields); ++i) {
9723 field = mono_array_get (fields, gpointer, i);
9724 get_field_name_and_type (field, &fname, &ftype);
9725 *p++ = 0x53; /* FIELD signature */
9726 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9731 g_assert (p - buffer <= buflen);
9732 buflen = p - buffer;
9733 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9734 p = mono_array_addr (result, char, 0);
9735 memcpy (p, buffer, buflen);
9737 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9743 * mono_reflection_setup_internal_class:
9744 * @tb: a TypeBuilder object
9746 * Creates a MonoClass that represents the TypeBuilder.
9747 * This is a trick that lets us simplify a lot of reflection code
9748 * (and will allow us to support Build and Run assemblies easier).
9751 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9754 MonoClass *klass, *parent;
9756 MONO_ARCH_SAVE_REGS;
9758 RESOLVE_TYPE (tb->parent);
9760 mono_loader_lock ();
9763 /* check so we can compile corlib correctly */
9764 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9765 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9766 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9768 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9774 /* the type has already being created: it means we just have to change the parent */
9775 if (tb->type.type) {
9776 klass = mono_class_from_mono_type (tb->type.type);
9777 klass->parent = NULL;
9778 /* fool mono_class_setup_parent */
9779 klass->supertypes = NULL;
9780 mono_class_setup_parent (klass, parent);
9781 mono_class_setup_mono_type (klass);
9782 mono_loader_unlock ();
9786 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9788 klass->image = &tb->module->dynamic_image->image;
9790 klass->inited = 1; /* we lie to the runtime */
9791 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9792 if (!mono_error_ok (&error))
9794 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9795 if (!mono_error_ok (&error))
9797 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9798 klass->flags = tb->attrs;
9800 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9802 klass->element_class = klass;
9804 if (mono_class_get_ref_info (klass) == NULL) {
9806 mono_class_set_ref_info (klass, tb);
9808 /* Put into cache so mono_class_get () will find it.
9809 Skip nested types as those should not be available on the global scope. */
9810 if (!tb->nesting_type) {
9811 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9813 klass->image->reflection_info_unregister_classes =
9814 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9817 g_assert (mono_class_get_ref_info (klass) == tb);
9820 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9821 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9823 if (parent != NULL) {
9824 mono_class_setup_parent (klass, parent);
9825 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9826 const char *old_n = klass->name;
9827 /* trick to get relative numbering right when compiling corlib */
9828 klass->name = "BuildingObject";
9829 mono_class_setup_parent (klass, mono_defaults.object_class);
9830 klass->name = old_n;
9833 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9834 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9835 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9836 klass->instance_size = sizeof (MonoObject);
9837 klass->size_inited = 1;
9838 mono_class_setup_vtable_general (klass, NULL, 0);
9841 mono_class_setup_mono_type (klass);
9843 mono_class_setup_supertypes (klass);
9846 * FIXME: handle interfaces.
9849 tb->type.type = &klass->byval_arg;
9851 if (tb->nesting_type) {
9852 g_assert (tb->nesting_type->type);
9853 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9856 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9858 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9860 mono_loader_unlock ();
9864 mono_loader_unlock ();
9865 mono_error_raise_exception (&error);
9869 * mono_reflection_setup_generic_class:
9870 * @tb: a TypeBuilder object
9872 * Setup the generic class before adding the first generic parameter.
9875 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9880 * mono_reflection_create_generic_class:
9881 * @tb: a TypeBuilder object
9883 * Creates the generic class after all generic parameters have been added.
9886 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9891 MONO_ARCH_SAVE_REGS;
9893 klass = mono_class_from_mono_type (tb->type.type);
9895 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9897 if (klass->generic_container || (count == 0))
9900 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9902 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9904 klass->generic_container->owner.klass = klass;
9905 klass->generic_container->type_argc = count;
9906 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9908 klass->is_generic = 1;
9910 for (i = 0; i < count; i++) {
9911 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9912 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9913 klass->generic_container->type_params [i] = *param;
9914 /*Make sure we are a diferent type instance */
9915 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9916 klass->generic_container->type_params [i].info.pklass = NULL;
9917 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9919 g_assert (klass->generic_container->type_params [i].param.owner);
9922 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9926 * mono_reflection_create_internal_class:
9927 * @tb: a TypeBuilder object
9929 * Actually create the MonoClass that is associated with the TypeBuilder.
9932 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9936 MONO_ARCH_SAVE_REGS;
9938 klass = mono_class_from_mono_type (tb->type.type);
9940 mono_loader_lock ();
9941 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9942 MonoReflectionFieldBuilder *fb;
9944 MonoType *enum_basetype;
9946 g_assert (tb->fields != NULL);
9947 g_assert (mono_array_length (tb->fields) >= 1);
9949 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9951 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9952 mono_loader_unlock ();
9956 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9957 klass->element_class = mono_class_from_mono_type (enum_basetype);
9958 if (!klass->element_class)
9959 klass->element_class = mono_class_from_mono_type (enum_basetype);
9962 * get the element_class from the current corlib.
9964 ec = default_class_from_mono_type (enum_basetype);
9965 klass->instance_size = ec->instance_size;
9966 klass->size_inited = 1;
9968 * this is almost safe to do with enums and it's needed to be able
9969 * to create objects of the enum type (for use in SetConstant).
9971 /* FIXME: Does this mean enums can't have method overrides ? */
9972 mono_class_setup_vtable_general (klass, NULL, 0);
9974 mono_loader_unlock ();
9977 static MonoMarshalSpec*
9978 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9979 MonoReflectionMarshal *minfo)
9981 MonoMarshalSpec *res;
9983 res = image_g_new0 (image, MonoMarshalSpec, 1);
9984 res->native = minfo->type;
9986 switch (minfo->type) {
9987 case MONO_NATIVE_LPARRAY:
9988 res->data.array_data.elem_type = minfo->eltype;
9989 if (minfo->has_size) {
9990 res->data.array_data.param_num = minfo->param_num;
9991 res->data.array_data.num_elem = minfo->count;
9992 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9995 res->data.array_data.param_num = -1;
9996 res->data.array_data.num_elem = -1;
9997 res->data.array_data.elem_mult = -1;
10001 case MONO_NATIVE_BYVALTSTR:
10002 case MONO_NATIVE_BYVALARRAY:
10003 res->data.array_data.num_elem = minfo->count;
10006 case MONO_NATIVE_CUSTOM:
10007 if (minfo->marshaltyperef)
10008 res->data.custom_data.custom_name =
10009 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10010 if (minfo->mcookie)
10011 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10020 #endif /* !DISABLE_REFLECTION_EMIT */
10022 MonoReflectionMarshal*
10023 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10024 MonoMarshalSpec *spec)
10026 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10027 MonoReflectionMarshal *minfo;
10030 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10031 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10032 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10033 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10036 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10037 minfo->type = spec->native;
10039 switch (minfo->type) {
10040 case MONO_NATIVE_LPARRAY:
10041 minfo->eltype = spec->data.array_data.elem_type;
10042 minfo->count = spec->data.array_data.num_elem;
10043 minfo->param_num = spec->data.array_data.param_num;
10046 case MONO_NATIVE_BYVALTSTR:
10047 case MONO_NATIVE_BYVALARRAY:
10048 minfo->count = spec->data.array_data.num_elem;
10051 case MONO_NATIVE_CUSTOM:
10052 if (spec->data.custom_data.custom_name) {
10053 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10055 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10057 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10059 if (spec->data.custom_data.cookie)
10060 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10070 #ifndef DISABLE_REFLECTION_EMIT
10072 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10073 ReflectionMethodBuilder *rmb,
10074 MonoMethodSignature *sig)
10078 MonoMethodWrapper *wrapperm;
10079 MonoMarshalSpec **specs;
10080 MonoReflectionMethodAux *method_aux;
10085 mono_error_init (&error);
10087 * Methods created using a MethodBuilder should have their memory allocated
10088 * inside the image mempool, while dynamic methods should have their memory
10091 dynamic = rmb->refs != NULL;
10092 image = dynamic ? NULL : klass->image;
10095 g_assert (!klass->generic_class);
10097 mono_loader_lock ();
10099 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10100 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10101 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10103 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10105 wrapperm = (MonoMethodWrapper*)m;
10107 m->dynamic = dynamic;
10109 m->flags = rmb->attrs;
10110 m->iflags = rmb->iattrs;
10111 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10112 g_assert (mono_error_ok (&error));
10114 m->signature = sig;
10115 m->sre_method = TRUE;
10116 m->skip_visibility = rmb->skip_visibility;
10117 if (rmb->table_idx)
10118 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10120 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10121 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10122 m->string_ctor = 1;
10124 m->signature->pinvoke = 1;
10125 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10126 m->signature->pinvoke = 1;
10128 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10130 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10131 g_assert (mono_error_ok (&error));
10132 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10133 g_assert (mono_error_ok (&error));
10135 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10137 if (klass->image->dynamic)
10138 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10140 mono_loader_unlock ();
10143 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10144 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10145 MonoMethodHeader *header;
10147 gint32 max_stack, i;
10148 gint32 num_locals = 0;
10149 gint32 num_clauses = 0;
10153 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10154 code_size = rmb->ilgen->code_len;
10155 max_stack = rmb->ilgen->max_stack;
10156 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10157 if (rmb->ilgen->ex_handlers)
10158 num_clauses = method_count_clauses (rmb->ilgen);
10161 code = mono_array_addr (rmb->code, guint8, 0);
10162 code_size = mono_array_length (rmb->code);
10163 /* we probably need to run a verifier on the code... */
10173 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10174 header->code_size = code_size;
10175 header->code = image_g_malloc (image, code_size);
10176 memcpy ((char*)header->code, code, code_size);
10177 header->max_stack = max_stack;
10178 header->init_locals = rmb->init_locals;
10179 header->num_locals = num_locals;
10181 for (i = 0; i < num_locals; ++i) {
10182 MonoReflectionLocalBuilder *lb =
10183 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10185 header->locals [i] = image_g_new0 (image, MonoType, 1);
10186 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10189 header->num_clauses = num_clauses;
10191 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10192 rmb->ilgen, num_clauses);
10195 wrapperm->header = header;
10198 if (rmb->generic_params) {
10199 int count = mono_array_length (rmb->generic_params);
10200 MonoGenericContainer *container = rmb->generic_container;
10202 g_assert (container);
10204 container->type_argc = count;
10205 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10206 container->owner.method = m;
10208 m->is_generic = TRUE;
10209 mono_method_set_generic_container (m, container);
10211 for (i = 0; i < count; i++) {
10212 MonoReflectionGenericParam *gp =
10213 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10214 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10215 container->type_params [i] = *param;
10219 * The method signature might have pointers to generic parameters that belong to other methods.
10220 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10221 * generic parameters.
10223 for (i = 0; i < m->signature->param_count; ++i) {
10224 MonoType *t = m->signature->params [i];
10225 if (t->type == MONO_TYPE_MVAR) {
10226 MonoGenericParam *gparam = t->data.generic_param;
10227 if (gparam->num < count) {
10228 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10229 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10235 if (klass->generic_container) {
10236 container->parent = klass->generic_container;
10237 container->context.class_inst = klass->generic_container->context.class_inst;
10239 container->context.method_inst = mono_get_shared_generic_inst (container);
10243 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10247 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10249 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10250 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10251 for (i = 0; i < rmb->nrefs; ++i)
10252 data [i + 1] = rmb->refs [i];
10257 /* Parameter info */
10260 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10261 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10262 for (i = 0; i <= m->signature->param_count; ++i) {
10263 MonoReflectionParamBuilder *pb;
10264 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10265 if ((i > 0) && (pb->attrs)) {
10266 /* Make a copy since it might point to a shared type structure */
10267 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10268 m->signature->params [i - 1]->attrs = pb->attrs;
10271 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10272 MonoDynamicImage *assembly;
10273 guint32 idx, def_type, len;
10277 if (!method_aux->param_defaults) {
10278 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10279 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10281 assembly = (MonoDynamicImage*)klass->image;
10282 idx = encode_constant (assembly, pb->def_value, &def_type);
10283 /* Copy the data from the blob since it might get realloc-ed */
10284 p = assembly->blob.data + idx;
10285 len = mono_metadata_decode_blob_size (p, &p2);
10287 method_aux->param_defaults [i] = image_g_malloc (image, len);
10288 method_aux->param_default_types [i] = def_type;
10289 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10293 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10294 g_assert (mono_error_ok (&error));
10297 if (!method_aux->param_cattr)
10298 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10299 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10305 /* Parameter marshalling */
10308 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10309 MonoReflectionParamBuilder *pb;
10310 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10311 if (pb->marshal_info) {
10313 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10314 specs [pb->position] =
10315 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10319 if (specs != NULL) {
10321 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10322 method_aux->param_marshall = specs;
10325 if (klass->image->dynamic && method_aux)
10326 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10328 mono_loader_unlock ();
10334 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10336 ReflectionMethodBuilder rmb;
10337 MonoMethodSignature *sig;
10339 mono_loader_lock ();
10340 sig = ctor_builder_to_signature (klass->image, mb);
10341 mono_loader_unlock ();
10343 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10345 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10346 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10348 /* If we are in a generic class, we might be called multiple times from inflate_method */
10349 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10350 /* ilgen is no longer needed */
10354 return mb->mhandle;
10358 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10360 ReflectionMethodBuilder rmb;
10361 MonoMethodSignature *sig;
10363 mono_loader_lock ();
10364 sig = method_builder_to_signature (klass->image, mb);
10365 mono_loader_unlock ();
10367 reflection_methodbuilder_from_method_builder (&rmb, mb);
10369 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10370 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10372 /* If we are in a generic class, we might be called multiple times from inflate_method */
10373 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10374 /* ilgen is no longer needed */
10377 return mb->mhandle;
10380 static MonoClassField*
10381 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10383 MonoClassField *field;
10386 field = g_new0 (MonoClassField, 1);
10388 field->name = mono_string_to_utf8 (fb->name);
10389 if (fb->attrs || fb->modreq || fb->modopt) {
10390 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10391 field->type->attrs = fb->attrs;
10393 g_assert (klass->image->dynamic);
10394 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10395 g_free (field->type);
10396 field->type = custom;
10398 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10400 if (fb->offset != -1)
10401 field->offset = fb->offset;
10402 field->parent = klass;
10403 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10405 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10412 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10415 MonoReflectionTypeBuilder *tb = NULL;
10416 gboolean is_dynamic = FALSE;
10417 MonoDomain *domain;
10418 MonoClass *geninst;
10420 mono_loader_lock ();
10422 domain = mono_object_domain (type);
10424 if (is_sre_type_builder (mono_object_class (type))) {
10425 tb = (MonoReflectionTypeBuilder *) type;
10428 } else if (is_sre_generic_instance (mono_object_class (type))) {
10429 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10430 MonoReflectionType *gtd = rgi->generic_type;
10432 if (is_sre_type_builder (mono_object_class (gtd))) {
10433 tb = (MonoReflectionTypeBuilder *)gtd;
10438 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10439 if (tb && tb->generic_container)
10440 mono_reflection_create_generic_class (tb);
10442 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10443 if (!klass->generic_container) {
10444 mono_loader_unlock ();
10448 if (klass->wastypebuilder) {
10449 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10454 mono_loader_unlock ();
10456 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10458 return &geninst->byval_arg;
10462 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10464 MonoGenericClass *gclass;
10465 MonoGenericInst *inst;
10467 g_assert (klass->generic_container);
10469 inst = mono_metadata_get_generic_inst (type_argc, types);
10470 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10472 return mono_generic_class_get_class (gclass);
10475 MonoReflectionMethod*
10476 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10479 MonoMethod *method, *inflated;
10480 MonoMethodInflated *imethod;
10481 MonoGenericContext tmp_context;
10482 MonoGenericInst *ginst;
10483 MonoType **type_argv;
10486 MONO_ARCH_SAVE_REGS;
10488 /*FIXME but this no longer should happen*/
10489 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10490 #ifndef DISABLE_REFLECTION_EMIT
10491 MonoReflectionMethodBuilder *mb = NULL;
10492 MonoReflectionTypeBuilder *tb;
10495 mb = (MonoReflectionMethodBuilder *) rmethod;
10496 tb = (MonoReflectionTypeBuilder *) mb->type;
10497 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10499 method = methodbuilder_to_mono_method (klass, mb);
10501 g_assert_not_reached ();
10505 method = rmethod->method;
10508 klass = method->klass;
10510 if (method->is_inflated)
10511 method = ((MonoMethodInflated *) method)->declaring;
10513 count = mono_method_signature (method)->generic_param_count;
10514 if (count != mono_array_length (types))
10517 type_argv = g_new0 (MonoType *, count);
10518 for (i = 0; i < count; i++) {
10519 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10520 type_argv [i] = mono_reflection_type_get_handle (garg);
10522 ginst = mono_metadata_get_generic_inst (count, type_argv);
10523 g_free (type_argv);
10525 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10526 tmp_context.method_inst = ginst;
10528 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10529 imethod = (MonoMethodInflated *) inflated;
10531 /*FIXME but I think this is no longer necessary*/
10532 if (method->klass->image->dynamic) {
10533 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10535 * This table maps metadata structures representing inflated methods/fields
10536 * to the reflection objects representing their generic definitions.
10538 mono_loader_lock ();
10539 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10540 mono_loader_unlock ();
10543 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10546 #ifndef DISABLE_REFLECTION_EMIT
10548 static MonoMethod *
10549 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10551 MonoMethodInflated *imethod;
10552 MonoGenericContext *context;
10556 * With generic code sharing the klass might not be inflated.
10557 * This can happen because classes inflated with their own
10558 * type arguments are "normalized" to the uninflated class.
10560 if (!klass->generic_class)
10563 context = mono_class_get_context (klass);
10565 if (klass->method.count && klass->methods) {
10566 /* Find the already created inflated method */
10567 for (i = 0; i < klass->method.count; ++i) {
10568 g_assert (klass->methods [i]->is_inflated);
10569 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10572 g_assert (i < klass->method.count);
10573 imethod = (MonoMethodInflated*)klass->methods [i];
10575 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10578 if (method->is_generic && method->klass->image->dynamic) {
10579 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10581 mono_loader_lock ();
10582 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10583 mono_loader_unlock ();
10585 return (MonoMethod *) imethod;
10588 static MonoMethod *
10589 inflate_method (MonoReflectionType *type, MonoObject *obj)
10591 MonoMethod *method;
10594 MonoClass *type_class = mono_object_class (type);
10596 if (is_sre_generic_instance (type_class)) {
10597 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10598 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10599 } else if (is_sre_type_builder (type_class)) {
10600 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10601 } else if (type->type) {
10602 gklass = mono_class_from_mono_type (type->type);
10603 gklass = mono_class_get_generic_type_definition (gklass);
10605 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10608 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10609 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10610 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10612 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10613 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10614 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10615 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10616 method = ((MonoReflectionMethod *) obj)->method;
10618 method = NULL; /* prevent compiler warning */
10619 g_error ("can't handle type %s", obj->vtable->klass->name);
10622 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10625 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10627 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10628 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10631 MonoGenericClass *gclass;
10632 MonoDynamicGenericClass *dgclass;
10633 MonoClass *klass, *gklass;
10637 MONO_ARCH_SAVE_REGS;
10639 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10640 klass = mono_class_from_mono_type (gtype);
10641 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10642 gclass = gtype->data.generic_class;
10644 if (!gclass->is_dynamic)
10647 dgclass = (MonoDynamicGenericClass *) gclass;
10649 if (dgclass->initialized)
10652 gklass = gclass->container_class;
10653 mono_class_init (gklass);
10655 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10656 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10657 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10659 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10660 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10661 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10662 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10663 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10665 for (i = 0; i < dgclass->count_methods; i++) {
10666 MonoObject *obj = mono_array_get (methods, gpointer, i);
10668 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10671 for (i = 0; i < dgclass->count_ctors; i++) {
10672 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10674 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10677 for (i = 0; i < dgclass->count_fields; i++) {
10678 MonoObject *obj = mono_array_get (fields, gpointer, i);
10679 MonoClassField *field, *inflated_field = NULL;
10681 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10682 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10683 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10684 field = ((MonoReflectionField *) obj)->field;
10686 field = NULL; /* prevent compiler warning */
10687 g_assert_not_reached ();
10690 dgclass->fields [i] = *field;
10691 dgclass->fields [i].parent = klass;
10692 dgclass->fields [i].type = mono_class_inflate_generic_type (
10693 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10694 dgclass->field_generic_types [i] = field->type;
10695 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10696 dgclass->field_objects [i] = obj;
10698 if (inflated_field) {
10699 g_free (inflated_field);
10701 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10705 dgclass->initialized = TRUE;
10709 fix_partial_generic_class (MonoClass *klass)
10711 MonoClass *gklass = klass->generic_class->container_class;
10712 MonoDynamicGenericClass *dgclass;
10715 if (klass->wastypebuilder)
10718 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10719 if (klass->parent != gklass->parent) {
10721 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10722 if (mono_error_ok (&error)) {
10723 MonoClass *parent = mono_class_from_mono_type (parent_type);
10724 mono_metadata_free_type (parent_type);
10725 if (parent != klass->parent) {
10726 /*fool mono_class_setup_parent*/
10727 klass->supertypes = NULL;
10728 mono_class_setup_parent (klass, parent);
10731 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10732 mono_error_cleanup (&error);
10733 if (gklass->wastypebuilder)
10734 klass->wastypebuilder = TRUE;
10739 if (!dgclass->initialized)
10742 if (klass->method.count != gklass->method.count) {
10743 klass->method.count = gklass->method.count;
10744 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10746 for (i = 0; i < klass->method.count; i++) {
10747 klass->methods [i] = mono_class_inflate_generic_method_full (
10748 gklass->methods [i], klass, mono_class_get_context (klass));
10752 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10753 klass->interface_count = gklass->interface_count;
10754 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10755 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10757 for (i = 0; i < gklass->interface_count; ++i) {
10758 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10759 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10760 mono_metadata_free_type (iface_type);
10762 ensure_runtime_vtable (klass->interfaces [i]);
10764 klass->interfaces_inited = 1;
10767 if (klass->field.count != gklass->field.count) {
10768 klass->field.count = gklass->field.count;
10769 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10771 for (i = 0; i < klass->field.count; i++) {
10772 klass->fields [i] = gklass->fields [i];
10773 klass->fields [i].parent = klass;
10774 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10778 /*We can only finish with this klass once it's parent has as well*/
10779 if (gklass->wastypebuilder)
10780 klass->wastypebuilder = TRUE;
10785 ensure_generic_class_runtime_vtable (MonoClass *klass)
10787 MonoClass *gklass = klass->generic_class->container_class;
10789 ensure_runtime_vtable (gklass);
10791 fix_partial_generic_class (klass);
10795 ensure_runtime_vtable (MonoClass *klass)
10797 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10800 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10803 ensure_runtime_vtable (klass->parent);
10806 num = tb->ctors? mono_array_length (tb->ctors): 0;
10807 num += tb->num_methods;
10808 klass->method.count = num;
10809 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10810 num = tb->ctors? mono_array_length (tb->ctors): 0;
10811 for (i = 0; i < num; ++i)
10812 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10813 num = tb->num_methods;
10815 for (i = 0; i < num; ++i)
10816 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10818 if (tb->interfaces) {
10819 klass->interface_count = mono_array_length (tb->interfaces);
10820 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10821 for (i = 0; i < klass->interface_count; ++i) {
10822 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10823 klass->interfaces [i] = mono_class_from_mono_type (iface);
10824 ensure_runtime_vtable (klass->interfaces [i]);
10826 klass->interfaces_inited = 1;
10828 } else if (klass->generic_class){
10829 ensure_generic_class_runtime_vtable (klass);
10832 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10833 for (i = 0; i < klass->method.count; ++i)
10834 klass->methods [i]->slot = i;
10836 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10837 mono_class_setup_interface_offsets (klass);
10838 mono_class_setup_interface_id (klass);
10842 * The generic vtable is needed even if image->run is not set since some
10843 * runtime code like ves_icall_Type_GetMethodsByName depends on
10844 * method->slot being defined.
10848 * tb->methods could not be freed since it is used for determining
10849 * overrides during dynamic vtable construction.
10854 mono_reflection_method_get_handle (MonoObject *method)
10856 MonoClass *class = mono_object_class (method);
10857 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10858 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10859 return sr_method->method;
10861 if (is_sre_method_builder (class)) {
10862 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10863 return mb->mhandle;
10865 if (is_sre_method_on_tb_inst (class)) {
10866 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10867 MonoMethod *result;
10868 /*FIXME move this to a proper method and unify with resolve_object*/
10869 if (m->method_args) {
10870 result = mono_reflection_method_on_tb_inst_get_handle (m);
10872 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10873 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10874 MonoMethod *mono_method;
10876 if (is_sre_method_builder (mono_object_class (m->mb)))
10877 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10878 else if (is_sr_mono_method (mono_object_class (m->mb)))
10879 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10881 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)));
10883 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10888 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10893 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10895 MonoReflectionTypeBuilder *tb;
10899 *num_overrides = 0;
10901 g_assert (klass->image->dynamic);
10903 if (!mono_class_get_ref_info (klass))
10906 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10908 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10912 for (i = 0; i < tb->num_methods; ++i) {
10913 MonoReflectionMethodBuilder *mb =
10914 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10915 if (mb->override_method)
10921 *overrides = g_new0 (MonoMethod*, onum * 2);
10924 for (i = 0; i < tb->num_methods; ++i) {
10925 MonoReflectionMethodBuilder *mb =
10926 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10927 if (mb->override_method) {
10928 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10929 (*overrides) [onum * 2 + 1] = mb->mhandle;
10931 g_assert (mb->mhandle);
10938 *num_overrides = onum;
10942 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10944 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10945 MonoReflectionFieldBuilder *fb;
10946 MonoClassField *field;
10947 MonoImage *image = klass->image;
10948 const char *p, *p2;
10950 guint32 len, idx, real_size = 0;
10952 klass->field.count = tb->num_fields;
10953 klass->field.first = 0;
10955 mono_error_init (error);
10957 if (tb->class_size) {
10958 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10959 klass->packing_size = tb->packing_size;
10960 real_size = klass->instance_size + tb->class_size;
10963 if (!klass->field.count) {
10964 klass->instance_size = MAX (klass->instance_size, real_size);
10968 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10969 mono_class_alloc_ext (klass);
10970 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10972 This is, guess what, a hack.
10973 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10974 On the static path no field class is resolved, only types are built. This is the right thing to do
10976 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10978 klass->size_inited = 1;
10980 for (i = 0; i < klass->field.count; ++i) {
10981 fb = mono_array_get (tb->fields, gpointer, i);
10982 field = &klass->fields [i];
10983 field->name = mono_string_to_utf8_image (image, fb->name, error);
10984 if (!mono_error_ok (error))
10987 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10988 field->type->attrs = fb->attrs;
10990 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10992 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10993 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10994 if (fb->offset != -1)
10995 field->offset = fb->offset;
10996 field->parent = klass;
10997 fb->handle = field;
10998 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11000 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11001 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11003 if (fb->def_value) {
11004 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11005 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11006 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11007 /* Copy the data from the blob since it might get realloc-ed */
11008 p = assembly->blob.data + idx;
11009 len = mono_metadata_decode_blob_size (p, &p2);
11011 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11012 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11016 klass->instance_size = MAX (klass->instance_size, real_size);
11017 mono_class_layout_fields (klass);
11021 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11023 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11024 MonoReflectionPropertyBuilder *pb;
11025 MonoImage *image = klass->image;
11026 MonoProperty *properties;
11029 mono_error_init (error);
11032 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11034 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11035 klass->ext->property.first = 0;
11037 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11038 klass->ext->properties = properties;
11039 for (i = 0; i < klass->ext->property.count; ++i) {
11040 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11041 properties [i].parent = klass;
11042 properties [i].attrs = pb->attrs;
11043 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11044 if (!mono_error_ok (error))
11046 if (pb->get_method)
11047 properties [i].get = pb->get_method->mhandle;
11048 if (pb->set_method)
11049 properties [i].set = pb->set_method->mhandle;
11051 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11052 if (pb->def_value) {
11054 const char *p, *p2;
11055 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11056 if (!klass->ext->prop_def_values)
11057 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11058 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11059 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11060 /* Copy the data from the blob since it might get realloc-ed */
11061 p = assembly->blob.data + idx;
11062 len = mono_metadata_decode_blob_size (p, &p2);
11064 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11065 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11070 MonoReflectionEvent *
11071 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11073 MonoEvent *event = g_new0 (MonoEvent, 1);
11076 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11078 event->parent = klass;
11079 event->attrs = eb->attrs;
11080 event->name = mono_string_to_utf8 (eb->name);
11081 if (eb->add_method)
11082 event->add = eb->add_method->mhandle;
11083 if (eb->remove_method)
11084 event->remove = eb->remove_method->mhandle;
11085 if (eb->raise_method)
11086 event->raise = eb->raise_method->mhandle;
11088 #ifndef MONO_SMALL_CONFIG
11089 if (eb->other_methods) {
11091 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11092 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11093 MonoReflectionMethodBuilder *mb =
11094 mono_array_get (eb->other_methods,
11095 MonoReflectionMethodBuilder*, j);
11096 event->other [j] = mb->mhandle;
11101 return mono_event_get_object (mono_object_domain (tb), klass, event);
11105 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11107 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11108 MonoReflectionEventBuilder *eb;
11109 MonoImage *image = klass->image;
11113 mono_error_init (error);
11116 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11118 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11119 klass->ext->event.first = 0;
11121 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11122 klass->ext->events = events;
11123 for (i = 0; i < klass->ext->event.count; ++i) {
11124 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11125 events [i].parent = klass;
11126 events [i].attrs = eb->attrs;
11127 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11128 if (!mono_error_ok (error))
11130 if (eb->add_method)
11131 events [i].add = eb->add_method->mhandle;
11132 if (eb->remove_method)
11133 events [i].remove = eb->remove_method->mhandle;
11134 if (eb->raise_method)
11135 events [i].raise = eb->raise_method->mhandle;
11137 #ifndef MONO_SMALL_CONFIG
11138 if (eb->other_methods) {
11140 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11141 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11142 MonoReflectionMethodBuilder *mb =
11143 mono_array_get (eb->other_methods,
11144 MonoReflectionMethodBuilder*, j);
11145 events [i].other [j] = mb->mhandle;
11149 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11154 remove_instantiations_of_and_ensure_contents (gpointer key,
11156 gpointer user_data)
11158 MonoType *type = (MonoType*)key;
11159 MonoClass *klass = (MonoClass*)user_data;
11161 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11162 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11169 check_array_for_usertypes (MonoArray *arr)
11176 for (i = 0; i < mono_array_length (arr); ++i)
11177 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11180 MonoReflectionType*
11181 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11185 MonoDomain* domain;
11186 MonoReflectionType* res;
11189 MONO_ARCH_SAVE_REGS;
11191 domain = mono_object_domain (tb);
11192 klass = mono_class_from_mono_type (tb->type.type);
11195 * Check for user defined Type subclasses.
11197 RESOLVE_TYPE (tb->parent);
11198 check_array_for_usertypes (tb->interfaces);
11200 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11201 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11203 RESOLVE_TYPE (fb->type);
11204 check_array_for_usertypes (fb->modreq);
11205 check_array_for_usertypes (fb->modopt);
11206 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11207 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11212 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11213 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11215 RESOLVE_TYPE (mb->rtype);
11216 check_array_for_usertypes (mb->return_modreq);
11217 check_array_for_usertypes (mb->return_modopt);
11218 check_array_for_usertypes (mb->parameters);
11219 if (mb->param_modreq)
11220 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11221 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11222 if (mb->param_modopt)
11223 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11224 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11229 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11230 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11232 check_array_for_usertypes (mb->parameters);
11233 if (mb->param_modreq)
11234 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11235 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11236 if (mb->param_modopt)
11237 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11238 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11243 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11246 * we need to lock the domain because the lock will be taken inside
11247 * So, we need to keep the locking order correct.
11249 mono_loader_lock ();
11250 mono_domain_lock (domain);
11251 if (klass->wastypebuilder) {
11252 mono_domain_unlock (domain);
11253 mono_loader_unlock ();
11254 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11257 * Fields to set in klass:
11258 * the various flags: delegate/unicode/contextbound etc.
11260 klass->flags = tb->attrs;
11261 klass->has_cctor = 1;
11262 klass->has_finalize = 1;
11264 /* fool mono_class_setup_parent */
11265 klass->supertypes = NULL;
11266 mono_class_setup_parent (klass, klass->parent);
11267 mono_class_setup_mono_type (klass);
11270 if (!((MonoDynamicImage*)klass->image)->run) {
11271 if (klass->generic_container) {
11272 /* FIXME: The code below can't handle generic classes */
11273 klass->wastypebuilder = TRUE;
11274 mono_loader_unlock ();
11275 mono_domain_unlock (domain);
11276 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11281 /* enums are done right away */
11282 if (!klass->enumtype)
11283 ensure_runtime_vtable (klass);
11285 if (tb->subtypes) {
11286 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11287 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11288 mono_class_alloc_ext (klass);
11289 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)));
11293 klass->nested_classes_inited = TRUE;
11295 /* fields and object layout */
11296 if (klass->parent) {
11297 if (!klass->parent->size_inited)
11298 mono_class_init (klass->parent);
11299 klass->instance_size = klass->parent->instance_size;
11300 klass->sizes.class_size = 0;
11301 klass->min_align = klass->parent->min_align;
11302 /* if the type has no fields we won't call the field_setup
11303 * routine which sets up klass->has_references.
11305 klass->has_references |= klass->parent->has_references;
11307 klass->instance_size = sizeof (MonoObject);
11308 klass->min_align = 1;
11311 /* FIXME: handle packing_size and instance_size */
11312 typebuilder_setup_fields (klass, &error);
11313 if (!mono_error_ok (&error))
11315 typebuilder_setup_properties (klass, &error);
11316 if (!mono_error_ok (&error))
11319 typebuilder_setup_events (klass, &error);
11320 if (!mono_error_ok (&error))
11323 klass->wastypebuilder = TRUE;
11326 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11327 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11328 * we want to return normal System.MonoType objects, so clear these out from the cache.
11330 * Together with this we must ensure the contents of all instances to match the created type.
11332 if (domain->type_hash && klass->generic_container)
11333 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11335 mono_domain_unlock (domain);
11336 mono_loader_unlock ();
11338 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11339 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11340 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11343 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11344 g_assert (res != (MonoReflectionType*)tb);
11349 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11350 klass->wastypebuilder = TRUE;
11351 mono_domain_unlock (domain);
11352 mono_loader_unlock ();
11353 mono_error_raise_exception (&error);
11358 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11360 MonoGenericParamFull *param;
11364 MONO_ARCH_SAVE_REGS;
11366 param = g_new0 (MonoGenericParamFull, 1);
11368 if (gparam->mbuilder) {
11369 if (!gparam->mbuilder->generic_container) {
11370 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11371 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11372 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11373 gparam->mbuilder->generic_container->is_method = TRUE;
11375 * Cannot set owner.method, since the MonoMethod is not created yet.
11376 * Set the image field instead, so type_in_image () works.
11378 gparam->mbuilder->generic_container->image = klass->image;
11380 param->param.owner = gparam->mbuilder->generic_container;
11381 } else if (gparam->tbuilder) {
11382 if (!gparam->tbuilder->generic_container) {
11383 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11384 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11385 gparam->tbuilder->generic_container->owner.klass = klass;
11387 param->param.owner = gparam->tbuilder->generic_container;
11390 param->info.name = mono_string_to_utf8 (gparam->name);
11391 param->param.num = gparam->index;
11393 image = &gparam->tbuilder->module->dynamic_image->image;
11394 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11396 gparam->type.type = &pklass->byval_arg;
11398 mono_class_set_ref_info (pklass, gparam);
11399 mono_image_lock (image);
11400 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11401 mono_image_unlock (image);
11405 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11407 MonoReflectionModuleBuilder *module = sig->module;
11408 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11409 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11414 check_array_for_usertypes (sig->arguments);
11416 sigbuffer_init (&buf, 32);
11418 sigbuffer_add_value (&buf, 0x07);
11419 sigbuffer_add_value (&buf, na);
11420 if (assembly != NULL){
11421 for (i = 0; i < na; ++i) {
11422 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11423 encode_reflection_type (assembly, type, &buf);
11427 buflen = buf.p - buf.buf;
11428 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11429 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11430 sigbuffer_free (&buf);
11436 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11438 MonoDynamicImage *assembly = sig->module->dynamic_image;
11439 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11444 check_array_for_usertypes (sig->arguments);
11446 sigbuffer_init (&buf, 32);
11448 sigbuffer_add_value (&buf, 0x06);
11449 for (i = 0; i < na; ++i) {
11450 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11451 encode_reflection_type (assembly, type, &buf);
11454 buflen = buf.p - buf.buf;
11455 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11456 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11457 sigbuffer_free (&buf);
11463 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11465 ReflectionMethodBuilder rmb;
11466 MonoMethodSignature *sig;
11471 sig = dynamic_method_to_signature (mb);
11473 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11476 * Resolve references.
11479 * Every second entry in the refs array is reserved for storing handle_class,
11480 * which is needed by the ldtoken implementation in the JIT.
11482 rmb.nrefs = mb->nrefs;
11483 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11484 for (i = 0; i < mb->nrefs; i += 2) {
11485 MonoClass *handle_class;
11487 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11489 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11490 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11492 * The referenced DynamicMethod should already be created by the managed
11493 * code, except in the case of circular references. In that case, we store
11494 * method in the refs array, and fix it up later when the referenced
11495 * DynamicMethod is created.
11497 if (method->mhandle) {
11498 ref = method->mhandle;
11500 /* FIXME: GC object stored in unmanaged memory */
11503 /* FIXME: GC object stored in unmanaged memory */
11504 method->referenced_by = g_slist_append (method->referenced_by, mb);
11506 handle_class = mono_defaults.methodhandle_class;
11508 MonoException *ex = NULL;
11509 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11511 ex = mono_get_exception_type_load (NULL, NULL);
11512 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11513 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11517 mono_raise_exception (ex);
11522 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11523 rmb.refs [i + 1] = handle_class;
11526 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11528 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11530 /* Fix up refs entries pointing at us */
11531 for (l = mb->referenced_by; l; l = l->next) {
11532 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11533 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11536 g_assert (method->mhandle);
11538 data = (gpointer*)wrapper->method_data;
11539 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11540 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11541 data [i + 1] = mb->mhandle;
11544 g_slist_free (mb->referenced_by);
11548 /* ilgen is no longer needed */
11552 #endif /* DISABLE_REFLECTION_EMIT */
11555 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11560 mono_runtime_free_method (
11561 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11566 * mono_reflection_is_valid_dynamic_token:
11568 * Returns TRUE if token is valid.
11572 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11574 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11577 #ifndef DISABLE_REFLECTION_EMIT
11580 * mono_reflection_lookup_dynamic_token:
11582 * Finish the Builder object pointed to by TOKEN and return the corresponding
11583 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11584 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11587 * LOCKING: Take the loader lock
11590 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11592 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11596 mono_loader_lock ();
11597 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11598 mono_loader_unlock ();
11601 g_error ("Could not find required dynamic token 0x%08x", token);
11607 handle_class = &klass;
11608 return resolve_object (image, obj, handle_class, context);
11611 MonoMethodSignature *
11612 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11614 MonoMethodSignature *sig;
11615 g_assert (image->dynamic);
11617 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11621 return mono_method_signature (method);
11625 * ensure_complete_type:
11627 * Ensure that KLASS is completed if it is a dynamic type, or references
11631 ensure_complete_type (MonoClass *klass)
11633 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11634 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11636 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11638 // Asserting here could break a lot of code
11639 //g_assert (klass->wastypebuilder);
11642 if (klass->generic_class) {
11643 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11646 for (i = 0; i < inst->type_argc; ++i) {
11647 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11653 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11655 gpointer result = NULL;
11657 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11658 result = mono_string_intern ((MonoString*)obj);
11659 *handle_class = mono_defaults.string_class;
11661 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11662 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11663 MonoClass *mc = mono_class_from_mono_type (type);
11664 if (!mono_class_init (mc))
11665 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11668 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11669 result = mono_class_from_mono_type (inflated);
11670 mono_metadata_free_type (inflated);
11672 result = mono_class_from_mono_type (type);
11674 *handle_class = mono_defaults.typehandle_class;
11676 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11677 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11678 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11679 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11680 result = ((MonoReflectionMethod*)obj)->method;
11682 result = mono_class_inflate_generic_method (result, context);
11683 *handle_class = mono_defaults.methodhandle_class;
11685 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11686 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11687 result = mb->mhandle;
11689 /* Type is not yet created */
11690 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11692 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11695 * Hopefully this has been filled in by calling CreateType() on the
11699 * TODO: This won't work if the application finishes another
11700 * TypeBuilder instance instead of this one.
11702 result = mb->mhandle;
11705 result = mono_class_inflate_generic_method (result, context);
11706 *handle_class = mono_defaults.methodhandle_class;
11707 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11708 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11710 result = cb->mhandle;
11712 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11714 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11715 result = cb->mhandle;
11718 result = mono_class_inflate_generic_method (result, context);
11719 *handle_class = mono_defaults.methodhandle_class;
11720 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11721 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11723 ensure_complete_type (field->parent);
11725 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11726 MonoClass *class = mono_class_from_mono_type (inflated);
11727 MonoClassField *inflated_field;
11728 gpointer iter = NULL;
11729 mono_metadata_free_type (inflated);
11730 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11731 if (!strcmp (field->name, inflated_field->name))
11734 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11735 result = inflated_field;
11739 *handle_class = mono_defaults.fieldhandle_class;
11741 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11742 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11743 result = fb->handle;
11746 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11748 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11749 result = fb->handle;
11752 if (fb->handle && fb->handle->parent->generic_container) {
11753 MonoClass *klass = fb->handle->parent;
11754 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11755 MonoClass *inflated = mono_class_from_mono_type (type);
11757 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11759 mono_metadata_free_type (type);
11761 *handle_class = mono_defaults.fieldhandle_class;
11762 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11763 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11764 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11767 klass = type->data.klass;
11768 if (klass->wastypebuilder) {
11769 /* Already created */
11773 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11774 result = type->data.klass;
11777 *handle_class = mono_defaults.typehandle_class;
11778 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11779 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11780 MonoMethodSignature *sig;
11783 if (helper->arguments)
11784 nargs = mono_array_length (helper->arguments);
11788 sig = mono_metadata_signature_alloc (image, nargs);
11789 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11790 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11792 if (helper->unmanaged_call_conv) { /* unmanaged */
11793 sig->call_convention = helper->unmanaged_call_conv - 1;
11794 sig->pinvoke = TRUE;
11795 } else if (helper->call_conv & 0x02) {
11796 sig->call_convention = MONO_CALL_VARARG;
11798 sig->call_convention = MONO_CALL_DEFAULT;
11801 sig->param_count = nargs;
11802 /* TODO: Copy type ? */
11803 sig->ret = helper->return_type->type;
11804 for (i = 0; i < nargs; ++i)
11805 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11808 *handle_class = NULL;
11809 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11810 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11811 /* Already created by the managed code */
11812 g_assert (method->mhandle);
11813 result = method->mhandle;
11814 *handle_class = mono_defaults.methodhandle_class;
11815 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11816 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11817 type = mono_class_inflate_generic_type (type, context);
11818 result = mono_class_from_mono_type (type);
11819 *handle_class = mono_defaults.typehandle_class;
11821 mono_metadata_free_type (type);
11822 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11823 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11824 type = mono_class_inflate_generic_type (type, context);
11825 result = mono_class_from_mono_type (type);
11826 *handle_class = mono_defaults.typehandle_class;
11828 mono_metadata_free_type (type);
11829 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11830 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11831 MonoClass *inflated;
11833 MonoClassField *field;
11835 if (is_sre_field_builder (mono_object_class (f->fb)))
11836 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11837 else if (is_sr_mono_field (mono_object_class (f->fb)))
11838 field = ((MonoReflectionField*)f->fb)->field;
11840 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)));
11842 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11843 inflated = mono_class_from_mono_type (type);
11845 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11846 ensure_complete_type (field->parent);
11848 mono_metadata_free_type (type);
11849 *handle_class = mono_defaults.fieldhandle_class;
11850 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11851 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11852 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11853 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11854 MonoMethod *method;
11856 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11857 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11858 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11859 method = ((MonoReflectionMethod *)c->cb)->method;
11861 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)));
11863 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11864 *handle_class = mono_defaults.methodhandle_class;
11865 mono_metadata_free_type (type);
11866 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11867 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11868 if (m->method_args) {
11869 result = mono_reflection_method_on_tb_inst_get_handle (m);
11871 result = mono_class_inflate_generic_method (result, context);
11873 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11874 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11875 MonoMethod *method;
11877 if (is_sre_method_builder (mono_object_class (m->mb)))
11878 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11879 else if (is_sr_mono_method (mono_object_class (m->mb)))
11880 method = ((MonoReflectionMethod *)m->mb)->method;
11882 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)));
11884 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11885 mono_metadata_free_type (type);
11887 *handle_class = mono_defaults.methodhandle_class;
11888 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11889 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11892 MonoMethod *method;
11896 mtype = mono_reflection_type_get_handle (m->parent);
11897 klass = mono_class_from_mono_type (mtype);
11899 /* Find the method */
11901 name = mono_string_to_utf8 (m->name);
11903 while ((method = mono_class_get_methods (klass, &iter))) {
11904 if (!strcmp (method->name, name))
11911 // FIXME: Check parameters/return value etc. match
11914 *handle_class = mono_defaults.methodhandle_class;
11915 } else if (is_sre_array (mono_object_get_class(obj)) ||
11916 is_sre_byref (mono_object_get_class(obj)) ||
11917 is_sre_pointer (mono_object_get_class(obj))) {
11918 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11919 MonoType *type = mono_reflection_type_get_handle (ref_type);
11920 result = mono_class_from_mono_type (type);
11921 *handle_class = mono_defaults.typehandle_class;
11923 g_print ("%s\n", obj->vtable->klass->name);
11924 g_assert_not_reached ();
11929 #else /* DISABLE_REFLECTION_EMIT */
11932 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11934 g_assert_not_reached ();
11939 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11941 g_assert_not_reached ();
11945 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11947 g_assert_not_reached ();
11951 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11953 g_assert_not_reached ();
11957 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11959 g_assert_not_reached ();
11963 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11965 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11969 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11971 g_assert_not_reached ();
11975 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11977 g_assert_not_reached ();
11980 MonoReflectionModule *
11981 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11983 g_assert_not_reached ();
11988 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11990 g_assert_not_reached ();
11995 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11997 g_assert_not_reached ();
12002 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12003 gboolean create_methodspec, gboolean register_token)
12005 g_assert_not_reached ();
12010 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12015 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12016 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12019 g_assert_not_reached ();
12023 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12026 *num_overrides = 0;
12029 MonoReflectionEvent *
12030 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12032 g_assert_not_reached ();
12036 MonoReflectionType*
12037 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12039 g_assert_not_reached ();
12044 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12046 g_assert_not_reached ();
12050 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12052 g_assert_not_reached ();
12057 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12059 g_assert_not_reached ();
12064 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12069 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12075 mono_reflection_type_get_handle (MonoReflectionType* ref)
12082 #endif /* DISABLE_REFLECTION_EMIT */
12084 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12085 const static guint32 declsec_flags_map[] = {
12086 0x00000000, /* empty */
12087 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12088 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12089 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12090 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12091 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12092 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12093 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12094 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12095 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12096 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12097 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12098 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12099 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12100 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12101 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12102 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12103 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12104 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12108 * Returns flags that includes all available security action associated to the handle.
12109 * @token: metadata token (either for a class or a method)
12110 * @image: image where resides the metadata.
12113 mono_declsec_get_flags (MonoImage *image, guint32 token)
12115 int index = mono_metadata_declsec_from_index (image, token);
12116 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12117 guint32 result = 0;
12121 /* HasSecurity can be present for other, not specially encoded, attributes,
12122 e.g. SuppressUnmanagedCodeSecurityAttribute */
12126 for (i = index; i < t->rows; i++) {
12127 guint32 cols [MONO_DECL_SECURITY_SIZE];
12129 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12130 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12133 action = cols [MONO_DECL_SECURITY_ACTION];
12134 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12135 result |= declsec_flags_map [action];
12137 g_assert_not_reached ();
12144 * Get the security actions (in the form of flags) associated with the specified method.
12146 * @method: The method for which we want the declarative security flags.
12147 * Return the declarative security flags for the method (only).
12149 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12150 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12153 mono_declsec_flags_from_method (MonoMethod *method)
12155 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12156 /* FIXME: No cache (for the moment) */
12157 guint32 idx = mono_method_get_index (method);
12158 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12159 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12160 return mono_declsec_get_flags (method->klass->image, idx);
12166 * Get the security actions (in the form of flags) associated with the specified class.
12168 * @klass: The class for which we want the declarative security flags.
12169 * Return the declarative security flags for the class.
12171 * Note: We cache the flags inside the MonoClass structure as this will get
12172 * called very often (at least for each method).
12175 mono_declsec_flags_from_class (MonoClass *klass)
12177 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12178 if (!klass->ext || !klass->ext->declsec_flags) {
12181 idx = mono_metadata_token_index (klass->type_token);
12182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12183 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12184 mono_loader_lock ();
12185 mono_class_alloc_ext (klass);
12186 mono_loader_unlock ();
12187 /* we cache the flags on classes */
12188 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12190 return klass->ext->declsec_flags;
12196 * Get the security actions (in the form of flags) associated with the specified assembly.
12198 * @assembly: The assembly for which we want the declarative security flags.
12199 * Return the declarative security flags for the assembly.
12202 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12204 guint32 idx = 1; /* there is only one assembly */
12205 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12206 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12207 return mono_declsec_get_flags (assembly->image, idx);
12212 * Fill actions for the specific index (which may either be an encoded class token or
12213 * an encoded method token) from the metadata image.
12214 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12217 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12218 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12220 MonoBoolean result = FALSE;
12222 guint32 cols [MONO_DECL_SECURITY_SIZE];
12223 int index = mono_metadata_declsec_from_index (image, token);
12226 t = &image->tables [MONO_TABLE_DECLSECURITY];
12227 for (i = index; i < t->rows; i++) {
12228 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12230 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12233 /* if present only replace (class) permissions with method permissions */
12234 /* if empty accept either class or method permissions */
12235 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12236 if (!actions->demand.blob) {
12237 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12238 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12239 actions->demand.blob = (char*) (blob + 2);
12240 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12243 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12244 if (!actions->noncasdemand.blob) {
12245 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12246 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12247 actions->noncasdemand.blob = (char*) (blob + 2);
12248 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12251 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12252 if (!actions->demandchoice.blob) {
12253 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12254 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12255 actions->demandchoice.blob = (char*) (blob + 2);
12256 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12266 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12267 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12269 guint32 idx = mono_metadata_token_index (klass->type_token);
12270 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12271 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12272 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12276 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12277 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12279 guint32 idx = mono_method_get_index (method);
12280 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12281 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12282 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12286 * Collect all actions (that requires to generate code in mini) assigned for
12287 * the specified method.
12288 * Note: Don't use the content of actions if the function return FALSE.
12291 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12293 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12294 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12295 MonoBoolean result = FALSE;
12298 /* quick exit if no declarative security is present in the metadata */
12299 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12302 /* we want the original as the wrapper is "free" of the security informations */
12303 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12304 method = mono_marshal_method_from_wrapper (method);
12309 /* First we look for method-level attributes */
12310 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12311 mono_class_init (method->klass);
12312 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12314 result = mono_declsec_get_method_demands_params (method, demands,
12315 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12318 /* Here we use (or create) the class declarative cache to look for demands */
12319 flags = mono_declsec_flags_from_class (method->klass);
12320 if (flags & mask) {
12322 mono_class_init (method->klass);
12323 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12325 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12326 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12329 /* The boolean return value is used as a shortcut in case nothing needs to
12330 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12336 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12338 * Note: Don't use the content of actions if the function return FALSE.
12341 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12343 MonoBoolean result = FALSE;
12346 /* quick exit if no declarative security is present in the metadata */
12347 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12350 /* we want the original as the wrapper is "free" of the security informations */
12351 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12352 method = mono_marshal_method_from_wrapper (method);
12357 /* results are independant - zeroize both */
12358 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12359 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12361 /* First we look for method-level attributes */
12362 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12363 mono_class_init (method->klass);
12365 result = mono_declsec_get_method_demands_params (method, cmethod,
12366 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12369 /* Here we use (or create) the class declarative cache to look for demands */
12370 flags = mono_declsec_flags_from_class (method->klass);
12371 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12372 mono_class_init (method->klass);
12374 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12375 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12382 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12384 * @klass The inherited class - this is the class that provides the security check (attributes)
12386 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12388 * Note: Don't use the content of actions if the function return FALSE.
12391 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12393 MonoBoolean result = FALSE;
12396 /* quick exit if no declarative security is present in the metadata */
12397 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12400 /* Here we use (or create) the class declarative cache to look for demands */
12401 flags = mono_declsec_flags_from_class (klass);
12402 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12403 mono_class_init (klass);
12404 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12406 result |= mono_declsec_get_class_demands_params (klass, demands,
12407 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12414 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12416 * Note: Don't use the content of actions if the function return FALSE.
12419 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12421 /* quick exit if no declarative security is present in the metadata */
12422 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12425 /* we want the original as the wrapper is "free" of the security informations */
12426 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12427 method = mono_marshal_method_from_wrapper (method);
12432 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12433 mono_class_init (method->klass);
12434 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12436 return mono_declsec_get_method_demands_params (method, demands,
12437 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12444 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12446 guint32 cols [MONO_DECL_SECURITY_SIZE];
12450 int index = mono_metadata_declsec_from_index (image, token);
12454 t = &image->tables [MONO_TABLE_DECLSECURITY];
12455 for (i = index; i < t->rows; i++) {
12456 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12458 /* shortcut - index are ordered */
12459 if (token != cols [MONO_DECL_SECURITY_PARENT])
12462 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12463 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12464 entry->blob = (char*) (metadata + 2);
12465 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12474 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12476 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12477 guint32 idx = mono_method_get_index (method);
12478 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12479 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12480 return get_declsec_action (method->klass->image, idx, action, entry);
12486 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12489 guint32 flags = mono_declsec_flags_from_class (klass);
12490 if (declsec_flags_map [action] & flags) {
12491 guint32 idx = mono_metadata_token_index (klass->type_token);
12492 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12493 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12494 return get_declsec_action (klass->image, idx, action, entry);
12500 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12502 guint32 idx = 1; /* there is only one assembly */
12503 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12504 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12506 return get_declsec_action (assembly->image, idx, action, entry);
12510 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12512 MonoObject *res, *exc;
12514 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12515 static MonoMethod *method = NULL;
12517 if (!System_Reflection_Emit_TypeBuilder) {
12518 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12519 g_assert (System_Reflection_Emit_TypeBuilder);
12521 if (method == NULL) {
12522 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12527 * The result of mono_type_get_object () might be a System.MonoType but we
12528 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12530 g_assert (mono_class_get_ref_info (klass));
12531 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12533 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12535 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12539 return *(MonoBoolean*)mono_object_unbox (res);