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>
43 static void* reflection_info_desc = NULL;
44 #define MOVING_GC_REGISTER(addr) do { \
45 if (!reflection_info_desc) { \
47 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
49 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
52 #define MOVING_GC_REGISTER(addr)
61 #define TEXT_OFFSET 512
62 #define CLI_H_SIZE 136
63 #define FILE_ALIGN 512
64 #define VIRT_ALIGN 8192
65 #define START_TEXT_RVA 0x00002000
68 MonoReflectionILGen *ilgen;
69 MonoReflectionType *rtype;
70 MonoArray *parameters;
71 MonoArray *generic_params;
72 MonoGenericContainer *generic_container;
78 guint32 *table_idx; /* note: it's a pointer */
82 MonoBoolean init_locals;
83 MonoBoolean skip_visibility;
84 MonoArray *return_modreq;
85 MonoArray *return_modopt;
86 MonoArray *param_modreq;
87 MonoArray *param_modopt;
88 MonoArray *permissions;
93 int charset, extra_flags, native_cc;
94 MonoString *dll, *dllentry;
95 } ReflectionMethodBuilder;
99 MonoReflectionGenericParam *gparam;
100 } GenericParamTableEntry;
102 const unsigned char table_sizes [MONO_TABLE_NUM] = {
112 MONO_INTERFACEIMPL_SIZE,
113 MONO_MEMBERREF_SIZE, /* 0x0A */
115 MONO_CUSTOM_ATTR_SIZE,
116 MONO_FIELD_MARSHAL_SIZE,
117 MONO_DECL_SECURITY_SIZE,
118 MONO_CLASS_LAYOUT_SIZE,
119 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
120 MONO_STAND_ALONE_SIGNATURE_SIZE,
124 MONO_PROPERTY_MAP_SIZE,
127 MONO_METHOD_SEMA_SIZE,
128 MONO_METHODIMPL_SIZE,
129 MONO_MODULEREF_SIZE, /* 0x1A */
135 MONO_ASSEMBLY_SIZE, /* 0x20 */
136 MONO_ASSEMBLY_PROCESSOR_SIZE,
137 MONO_ASSEMBLYOS_SIZE,
138 MONO_ASSEMBLYREF_SIZE,
139 MONO_ASSEMBLYREFPROC_SIZE,
140 MONO_ASSEMBLYREFOS_SIZE,
144 MONO_NESTED_CLASS_SIZE,
146 MONO_GENERICPARAM_SIZE, /* 0x2A */
147 MONO_METHODSPEC_SIZE,
148 MONO_GENPARCONSTRAINT_SIZE
152 #ifndef DISABLE_REFLECTION_EMIT
153 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
154 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
155 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
156 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
157 static void ensure_runtime_vtable (MonoClass *klass);
158 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
159 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
160 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
161 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
164 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
165 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
166 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
167 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
168 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
169 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
170 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
171 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
172 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
173 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
174 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
175 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
176 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
177 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
178 static gboolean is_sre_array (MonoClass *class);
179 static gboolean is_sre_byref (MonoClass *class);
180 static gboolean is_sre_pointer (MonoClass *class);
181 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
182 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
183 static MonoMethod * inflate_method (MonoReflectionGenericClass *type, MonoObject *obj);
185 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
186 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
187 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
188 __type = mono_reflection_type_resolve_user_types (__type); \
189 mono_array_set (arr, MonoReflectionType*, index, __type); \
192 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
195 mono_reflection_init (void)
200 sigbuffer_init (SigBuffer *buf, int size)
202 buf->buf = g_malloc (size);
204 buf->end = buf->buf + size;
208 sigbuffer_make_room (SigBuffer *buf, int size)
210 if (buf->end - buf->p < size) {
211 int new_size = buf->end - buf->buf + size + 32;
212 char *p = g_realloc (buf->buf, new_size);
213 size = buf->p - buf->buf;
216 buf->end = buf->buf + new_size;
221 sigbuffer_add_value (SigBuffer *buf, guint32 val)
223 sigbuffer_make_room (buf, 6);
224 mono_metadata_encode_value (val, buf->p, &buf->p);
228 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
230 sigbuffer_make_room (buf, 1);
236 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
238 sigbuffer_make_room (buf, size);
239 memcpy (buf->p, p, size);
244 sigbuffer_free (SigBuffer *buf)
249 #ifndef DISABLE_REFLECTION_EMIT
253 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
257 image_g_malloc (MonoImage *image, guint size)
260 return mono_image_alloc (image, size);
262 return g_malloc (size);
264 #endif /* !DISABLE_REFLECTION_EMIT */
269 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
273 image_g_malloc0 (MonoImage *image, guint size)
276 return mono_image_alloc0 (image, size);
278 return g_malloc0 (size);
281 #ifndef DISABLE_REFLECTION_EMIT
283 image_strdup (MonoImage *image, const char *s)
286 return mono_image_strdup (image, s);
292 #define image_g_new(image,struct_type, n_structs) \
293 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
295 #define image_g_new0(image,struct_type, n_structs) \
296 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
300 alloc_table (MonoDynamicTable *table, guint nrows)
303 g_assert (table->columns);
304 if (nrows + 1 >= table->alloc_rows) {
305 while (nrows + 1 >= table->alloc_rows) {
306 if (table->alloc_rows == 0)
307 table->alloc_rows = 16;
309 table->alloc_rows *= 2;
312 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
317 make_room_in_stream (MonoDynamicStream *stream, int size)
319 if (size <= stream->alloc_size)
322 while (stream->alloc_size <= size) {
323 if (stream->alloc_size < 4096)
324 stream->alloc_size = 4096;
326 stream->alloc_size *= 2;
329 stream->data = g_realloc (stream->data, stream->alloc_size);
333 string_heap_insert (MonoDynamicStream *sh, const char *str)
337 gpointer oldkey, oldval;
339 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
340 return GPOINTER_TO_UINT (oldval);
342 len = strlen (str) + 1;
345 make_room_in_stream (sh, idx + len);
348 * We strdup the string even if we already copy them in sh->data
349 * so that the string pointers in the hash remain valid even if
350 * we need to realloc sh->data. We may want to avoid that later.
352 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
353 memcpy (sh->data + idx, str, len);
359 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
361 char *name = mono_string_to_utf8 (str);
363 idx = string_heap_insert (sh, name);
368 #ifndef DISABLE_REFLECTION_EMIT
370 string_heap_init (MonoDynamicStream *sh)
373 sh->alloc_size = 4096;
374 sh->data = g_malloc (4096);
375 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
376 string_heap_insert (sh, "");
381 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
385 make_room_in_stream (stream, stream->index + len);
386 memcpy (stream->data + stream->index, data, len);
388 stream->index += len;
390 * align index? Not without adding an additional param that controls it since
391 * we may store a blob value in pieces.
397 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
401 make_room_in_stream (stream, stream->index + len);
402 memset (stream->data + stream->index, 0, len);
404 stream->index += len;
409 stream_data_align (MonoDynamicStream *stream)
412 guint32 count = stream->index % 4;
414 /* we assume the stream data will be aligned */
416 mono_image_add_stream_data (stream, buf, 4 - count);
419 #ifndef DISABLE_REFLECTION_EMIT
421 mono_blob_entry_hash (const char* str)
425 len = mono_metadata_decode_blob_size (str, &str);
429 for (str += 1; str < end; str++)
430 h = (h << 5) - h + *str;
438 mono_blob_entry_equal (const char *str1, const char *str2) {
442 len = mono_metadata_decode_blob_size (str1, &end1);
443 len2 = mono_metadata_decode_blob_size (str2, &end2);
446 return memcmp (end1, end2, len) == 0;
450 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
454 gpointer oldkey, oldval;
456 copy = g_malloc (s1+s2);
457 memcpy (copy, b1, s1);
458 memcpy (copy + s1, b2, s2);
459 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
461 idx = GPOINTER_TO_UINT (oldval);
463 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
464 mono_image_add_stream_data (&assembly->blob, b2, s2);
465 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
471 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
475 guint32 size = buf->p - buf->buf;
477 g_assert (size <= (buf->end - buf->buf));
478 mono_metadata_encode_value (size, b, &b);
479 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
483 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
484 * dest may be misaligned.
487 swap_with_size (char *dest, const char* val, int len, int nelem) {
488 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
491 for (elem = 0; elem < nelem; ++elem) {
517 g_assert_not_reached ();
523 memcpy (dest, val, len * nelem);
528 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
532 guint32 idx = 0, len;
534 len = str->length * 2;
535 mono_metadata_encode_value (len, b, &b);
536 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
538 char *swapped = g_malloc (2 * mono_string_length (str));
539 const char *p = (const char*)mono_string_chars (str);
541 swap_with_size (swapped, p, 2, mono_string_length (str));
542 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
546 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
551 #ifndef DISABLE_REFLECTION_EMIT
553 default_class_from_mono_type (MonoType *type)
555 switch (type->type) {
556 case MONO_TYPE_OBJECT:
557 return mono_defaults.object_class;
559 return mono_defaults.void_class;
560 case MONO_TYPE_BOOLEAN:
561 return mono_defaults.boolean_class;
563 return mono_defaults.char_class;
565 return mono_defaults.sbyte_class;
567 return mono_defaults.byte_class;
569 return mono_defaults.int16_class;
571 return mono_defaults.uint16_class;
573 return mono_defaults.int32_class;
575 return mono_defaults.uint32_class;
577 return mono_defaults.int_class;
579 return mono_defaults.uint_class;
581 return mono_defaults.int64_class;
583 return mono_defaults.uint64_class;
585 return mono_defaults.single_class;
587 return mono_defaults.double_class;
588 case MONO_TYPE_STRING:
589 return mono_defaults.string_class;
591 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
592 g_assert_not_reached ();
600 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
603 MonoGenericInst *class_inst;
608 class_inst = gclass->context.class_inst;
610 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
611 klass = gclass->container_class;
612 sigbuffer_add_value (buf, klass->byval_arg.type);
613 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
615 sigbuffer_add_value (buf, class_inst->type_argc);
616 for (i = 0; i < class_inst->type_argc; ++i)
617 encode_type (assembly, class_inst->type_argv [i], buf);
622 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
625 g_assert_not_reached ();
630 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
634 case MONO_TYPE_BOOLEAN:
648 case MONO_TYPE_STRING:
649 case MONO_TYPE_OBJECT:
650 case MONO_TYPE_TYPEDBYREF:
651 sigbuffer_add_value (buf, type->type);
654 sigbuffer_add_value (buf, type->type);
655 encode_type (assembly, type->data.type, buf);
657 case MONO_TYPE_SZARRAY:
658 sigbuffer_add_value (buf, type->type);
659 encode_type (assembly, &type->data.klass->byval_arg, buf);
661 case MONO_TYPE_VALUETYPE:
662 case MONO_TYPE_CLASS: {
663 MonoClass *k = mono_class_from_mono_type (type);
665 if (k->generic_container) {
666 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
667 encode_generic_class (assembly, gclass, buf);
670 * Make sure we use the correct type.
672 sigbuffer_add_value (buf, k->byval_arg.type);
674 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
675 * otherwise two typerefs could point to the same type, leading to
676 * verification errors.
678 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
682 case MONO_TYPE_ARRAY:
683 sigbuffer_add_value (buf, type->type);
684 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
685 sigbuffer_add_value (buf, type->data.array->rank);
686 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
687 sigbuffer_add_value (buf, 0);
689 case MONO_TYPE_GENERICINST:
690 encode_generic_class (assembly, type->data.generic_class, buf);
694 sigbuffer_add_value (buf, type->type);
695 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
698 g_error ("need to encode type %x", type->type);
703 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
706 sigbuffer_add_value (buf, MONO_TYPE_VOID);
710 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
714 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
719 for (i = 0; i < mono_array_length (modreq); ++i) {
720 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
721 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
722 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
726 for (i = 0; i < mono_array_length (modopt); ++i) {
727 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
728 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
729 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
734 #ifndef DISABLE_REFLECTION_EMIT
736 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
740 guint32 nparams = sig->param_count;
746 sigbuffer_init (&buf, 32);
748 * FIXME: vararg, explicit_this, differenc call_conv values...
750 idx = sig->call_convention;
752 idx |= 0x20; /* hasthis */
753 if (sig->generic_param_count)
754 idx |= 0x10; /* generic */
755 sigbuffer_add_byte (&buf, idx);
756 if (sig->generic_param_count)
757 sigbuffer_add_value (&buf, sig->generic_param_count);
758 sigbuffer_add_value (&buf, nparams);
759 encode_type (assembly, sig->ret, &buf);
760 for (i = 0; i < nparams; ++i) {
761 if (i == sig->sentinelpos)
762 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
763 encode_type (assembly, sig->params [i], &buf);
765 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
766 sigbuffer_free (&buf);
772 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
775 * FIXME: reuse code from method_encode_signature().
779 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
780 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
781 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
784 sigbuffer_init (&buf, 32);
785 /* LAMESPEC: all the call conv spec is foobared */
786 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
787 if (mb->call_conv & 2)
788 idx |= 0x5; /* vararg */
789 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
790 idx |= 0x20; /* hasthis */
792 idx |= 0x10; /* generic */
793 sigbuffer_add_byte (&buf, idx);
795 sigbuffer_add_value (&buf, ngparams);
796 sigbuffer_add_value (&buf, nparams + notypes);
797 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
798 encode_reflection_type (assembly, mb->rtype, &buf);
799 for (i = 0; i < nparams; ++i) {
800 MonoArray *modreq = NULL;
801 MonoArray *modopt = NULL;
802 MonoReflectionType *pt;
804 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
805 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
806 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
807 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
808 encode_custom_modifiers (assembly, modreq, modopt, &buf);
809 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
810 encode_reflection_type (assembly, pt, &buf);
813 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814 for (i = 0; i < notypes; ++i) {
815 MonoReflectionType *pt;
817 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
818 encode_reflection_type (assembly, pt, &buf);
821 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
822 sigbuffer_free (&buf);
827 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
829 MonoDynamicTable *table;
831 guint32 idx, sig_idx;
832 guint nl = mono_array_length (ilgen->locals);
836 sigbuffer_init (&buf, 32);
837 sigbuffer_add_value (&buf, 0x07);
838 sigbuffer_add_value (&buf, nl);
839 for (i = 0; i < nl; ++i) {
840 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
843 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
845 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
847 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
848 sigbuffer_free (&buf);
850 if (assembly->standalonesig_cache == NULL)
851 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
852 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
856 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
857 idx = table->next_idx ++;
859 alloc_table (table, table->rows);
860 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
862 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
864 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
870 method_count_clauses (MonoReflectionILGen *ilgen)
872 guint32 num_clauses = 0;
875 MonoILExceptionInfo *ex_info;
876 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
877 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
878 if (ex_info->handlers)
879 num_clauses += mono_array_length (ex_info->handlers);
887 #ifndef DISABLE_REFLECTION_EMIT
888 static MonoExceptionClause*
889 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
891 MonoExceptionClause *clauses;
892 MonoExceptionClause *clause;
893 MonoILExceptionInfo *ex_info;
894 MonoILExceptionBlock *ex_block;
895 guint32 finally_start;
896 int i, j, clause_index;;
898 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
901 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
902 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
903 finally_start = ex_info->start + ex_info->len;
904 if (!ex_info->handlers)
906 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
907 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
908 clause = &(clauses [clause_index]);
910 clause->flags = ex_block->type;
911 clause->try_offset = ex_info->start;
913 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
914 clause->try_len = finally_start - ex_info->start;
916 clause->try_len = ex_info->len;
917 clause->handler_offset = ex_block->start;
918 clause->handler_len = ex_block->len;
919 if (ex_block->extype) {
920 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
922 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
923 clause->data.filter_offset = ex_block->filter_offset;
925 clause->data.filter_offset = 0;
927 finally_start = ex_block->start + ex_block->len;
935 #endif /* !DISABLE_REFLECTION_EMIT */
938 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
944 gint32 num_locals = 0;
945 gint32 num_exception = 0;
948 char fat_header [12];
951 guint32 local_sig = 0;
952 guint32 header_size = 12;
955 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
956 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
960 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
962 code = mb->ilgen->code;
963 code_size = mb->ilgen->code_len;
964 max_stack = mb->ilgen->max_stack;
965 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
966 if (mb->ilgen->ex_handlers)
967 num_exception = method_count_clauses (mb->ilgen);
971 char *name = mono_string_to_utf8 (mb->name);
972 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
973 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
976 mono_raise_exception (exception);
979 code_size = mono_array_length (code);
980 max_stack = 8; /* we probably need to run a verifier on the code... */
983 stream_data_align (&assembly->code);
985 /* check for exceptions, maxstack, locals */
986 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
988 if (code_size < 64 && !(code_size & 1)) {
989 flags = (code_size << 2) | 0x2;
990 } else if (code_size < 32 && (code_size & 1)) {
991 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
995 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
996 /* add to the fixup todo list */
997 if (mb->ilgen && mb->ilgen->num_token_fixups)
998 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
999 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000 return assembly->text_rva + idx;
1004 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1006 * FIXME: need to set also the header size in fat_flags.
1007 * (and more sects and init locals flags)
1011 fat_flags |= METHOD_HEADER_MORE_SECTS;
1012 if (mb->init_locals)
1013 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1014 fat_header [0] = fat_flags;
1015 fat_header [1] = (header_size / 4 ) << 4;
1016 short_value = GUINT16_TO_LE (max_stack);
1017 memcpy (fat_header + 2, &short_value, 2);
1018 int_value = GUINT32_TO_LE (code_size);
1019 memcpy (fat_header + 4, &int_value, 4);
1020 int_value = GUINT32_TO_LE (local_sig);
1021 memcpy (fat_header + 8, &int_value, 4);
1022 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1023 /* add to the fixup todo list */
1024 if (mb->ilgen && mb->ilgen->num_token_fixups)
1025 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1027 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1028 if (num_exception) {
1029 unsigned char sheader [4];
1030 MonoILExceptionInfo * ex_info;
1031 MonoILExceptionBlock * ex_block;
1034 stream_data_align (&assembly->code);
1035 /* always use fat format for now */
1036 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1037 num_exception *= 6 * sizeof (guint32);
1038 num_exception += 4; /* include the size of the header */
1039 sheader [1] = num_exception & 0xff;
1040 sheader [2] = (num_exception >> 8) & 0xff;
1041 sheader [3] = (num_exception >> 16) & 0xff;
1042 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1043 /* fat header, so we are already aligned */
1045 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1046 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1047 if (ex_info->handlers) {
1048 int finally_start = ex_info->start + ex_info->len;
1049 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1051 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1053 val = GUINT32_TO_LE (ex_block->type);
1054 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1056 val = GUINT32_TO_LE (ex_info->start);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1058 /* need fault, too, probably */
1059 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1060 val = GUINT32_TO_LE (finally_start - ex_info->start);
1062 val = GUINT32_TO_LE (ex_info->len);
1063 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1064 /* handler offset */
1065 val = GUINT32_TO_LE (ex_block->start);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1068 val = GUINT32_TO_LE (ex_block->len);
1069 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070 finally_start = ex_block->start + ex_block->len;
1071 if (ex_block->extype) {
1072 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1074 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1075 val = ex_block->filter_offset;
1079 val = GUINT32_TO_LE (val);
1080 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1081 /*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",
1082 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);*/
1085 g_error ("No clauses for ex info block %d", i);
1089 return assembly->text_rva + idx;
1093 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1096 MonoDynamicTable *table;
1099 table = &assembly->tables [table_idx];
1101 g_assert (col < table->columns);
1103 values = table->values + table->columns;
1104 for (i = 1; i <= table->rows; ++i) {
1105 if (values [col] == token)
1107 values += table->columns;
1113 * LOCKING: Acquires the loader lock.
1115 static MonoCustomAttrInfo*
1116 lookup_custom_attr (MonoImage *image, gpointer member)
1118 MonoCustomAttrInfo* res;
1120 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1125 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1129 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1131 /* FIXME: Need to do more checks */
1132 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1133 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1135 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1142 static MonoCustomAttrInfo*
1143 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1145 int i, index, count, not_visible;
1146 MonoCustomAttrInfo *ainfo;
1147 MonoReflectionCustomAttr *cattr;
1151 /* FIXME: check in assembly the Run flag is set */
1153 count = mono_array_length (cattrs);
1155 /* Skip nonpublic attributes since MS.NET seems to do the same */
1156 /* FIXME: This needs to be done more globally */
1158 for (i = 0; i < count; ++i) {
1159 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1160 if (!custom_attr_visible (image, cattr))
1163 count -= not_visible;
1165 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1167 ainfo->image = image;
1168 ainfo->num_attrs = count;
1169 ainfo->cached = alloc_img != NULL;
1171 for (i = 0; i < count; ++i) {
1172 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1173 if (custom_attr_visible (image, cattr)) {
1174 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1175 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1176 ainfo->attrs [index].ctor = cattr->ctor->method;
1177 ainfo->attrs [index].data = saved;
1178 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1186 #ifndef DISABLE_REFLECTION_EMIT
1188 * LOCKING: Acquires the loader lock.
1191 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1193 MonoCustomAttrInfo *ainfo, *tmp;
1195 if (!cattrs || !mono_array_length (cattrs))
1198 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1200 mono_loader_lock ();
1201 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1203 mono_custom_attrs_free (tmp);
1204 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1205 mono_loader_unlock ();
1211 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1218 * idx is the table index of the object
1219 * type is one of MONO_CUSTOM_ATTR_*
1222 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1224 MonoDynamicTable *table;
1225 MonoReflectionCustomAttr *cattr;
1227 guint32 count, i, token;
1229 char *p = blob_size;
1231 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1234 count = mono_array_length (cattrs);
1235 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1236 table->rows += count;
1237 alloc_table (table, table->rows);
1238 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1239 idx <<= MONO_CUSTOM_ATTR_BITS;
1241 for (i = 0; i < count; ++i) {
1242 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1243 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1244 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1245 type = mono_metadata_token_index (token);
1246 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1247 switch (mono_metadata_token_table (token)) {
1248 case MONO_TABLE_METHOD:
1249 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1251 case MONO_TABLE_MEMBERREF:
1252 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1255 g_warning ("got wrong token in custom attr");
1258 values [MONO_CUSTOM_ATTR_TYPE] = type;
1260 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1261 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1262 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1263 values += MONO_CUSTOM_ATTR_SIZE;
1269 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1271 MonoDynamicTable *table;
1273 guint32 count, i, idx;
1274 MonoReflectionPermissionSet *perm;
1279 count = mono_array_length (permissions);
1280 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1281 table->rows += count;
1282 alloc_table (table, table->rows);
1284 for (i = 0; i < mono_array_length (permissions); ++i) {
1285 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1287 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1289 idx = mono_metadata_token_index (parent_token);
1290 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1291 switch (mono_metadata_token_table (parent_token)) {
1292 case MONO_TABLE_TYPEDEF:
1293 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1295 case MONO_TABLE_METHOD:
1296 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1298 case MONO_TABLE_ASSEMBLY:
1299 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1302 g_assert_not_reached ();
1305 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1306 values [MONO_DECL_SECURITY_PARENT] = idx;
1307 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1314 * Fill in the MethodDef and ParamDef tables for a method.
1315 * This is used for both normal methods and constructors.
1318 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1320 MonoDynamicTable *table;
1324 /* room in this table is already allocated */
1325 table = &assembly->tables [MONO_TABLE_METHOD];
1326 *mb->table_idx = table->next_idx ++;
1327 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1328 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1329 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1330 values [MONO_METHOD_FLAGS] = mb->attrs;
1331 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1332 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1333 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1335 table = &assembly->tables [MONO_TABLE_PARAM];
1336 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1338 mono_image_add_decl_security (assembly,
1339 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1342 MonoDynamicTable *mtable;
1345 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1346 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1349 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1350 if (mono_array_get (mb->pinfo, gpointer, i))
1353 table->rows += count;
1354 alloc_table (table, table->rows);
1355 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1356 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1357 MonoReflectionParamBuilder *pb;
1358 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1359 values [MONO_PARAM_FLAGS] = pb->attrs;
1360 values [MONO_PARAM_SEQUENCE] = i;
1361 if (pb->name != NULL) {
1362 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1364 values [MONO_PARAM_NAME] = 0;
1366 values += MONO_PARAM_SIZE;
1367 if (pb->marshal_info) {
1369 alloc_table (mtable, mtable->rows);
1370 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1371 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1372 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1374 pb->table_idx = table->next_idx++;
1375 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1376 guint32 field_type = 0;
1377 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1379 alloc_table (mtable, mtable->rows);
1380 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1381 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1382 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1383 mvalues [MONO_CONSTANT_TYPE] = field_type;
1384 mvalues [MONO_CONSTANT_PADDING] = 0;
1392 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1394 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1396 rmb->ilgen = mb->ilgen;
1397 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1398 rmb->parameters = mb->parameters;
1399 rmb->generic_params = mb->generic_params;
1400 rmb->generic_container = mb->generic_container;
1401 rmb->opt_types = NULL;
1402 rmb->pinfo = mb->pinfo;
1403 rmb->attrs = mb->attrs;
1404 rmb->iattrs = mb->iattrs;
1405 rmb->call_conv = mb->call_conv;
1406 rmb->code = mb->code;
1407 rmb->type = mb->type;
1408 rmb->name = mb->name;
1409 rmb->table_idx = &mb->table_idx;
1410 rmb->init_locals = mb->init_locals;
1411 rmb->skip_visibility = FALSE;
1412 rmb->return_modreq = mb->return_modreq;
1413 rmb->return_modopt = mb->return_modopt;
1414 rmb->param_modreq = mb->param_modreq;
1415 rmb->param_modopt = mb->param_modopt;
1416 rmb->permissions = mb->permissions;
1417 rmb->mhandle = mb->mhandle;
1422 rmb->charset = mb->charset;
1423 rmb->extra_flags = mb->extra_flags;
1424 rmb->native_cc = mb->native_cc;
1425 rmb->dllentry = mb->dllentry;
1431 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1433 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1435 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1437 rmb->ilgen = mb->ilgen;
1438 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1439 rmb->parameters = mb->parameters;
1440 rmb->generic_params = NULL;
1441 rmb->generic_container = NULL;
1442 rmb->opt_types = NULL;
1443 rmb->pinfo = mb->pinfo;
1444 rmb->attrs = mb->attrs;
1445 rmb->iattrs = mb->iattrs;
1446 rmb->call_conv = mb->call_conv;
1448 rmb->type = mb->type;
1449 rmb->name = mono_string_new (mono_domain_get (), name);
1450 rmb->table_idx = &mb->table_idx;
1451 rmb->init_locals = mb->init_locals;
1452 rmb->skip_visibility = FALSE;
1453 rmb->return_modreq = NULL;
1454 rmb->return_modopt = NULL;
1455 rmb->param_modreq = mb->param_modreq;
1456 rmb->param_modopt = mb->param_modopt;
1457 rmb->permissions = mb->permissions;
1458 rmb->mhandle = mb->mhandle;
1463 #ifndef DISABLE_REFLECTION_EMIT
1465 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1467 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1469 rmb->ilgen = mb->ilgen;
1470 rmb->rtype = mb->rtype;
1471 rmb->parameters = mb->parameters;
1472 rmb->generic_params = NULL;
1473 rmb->generic_container = NULL;
1474 rmb->opt_types = NULL;
1476 rmb->attrs = mb->attrs;
1478 rmb->call_conv = mb->call_conv;
1480 rmb->type = (MonoObject *) mb->owner;
1481 rmb->name = mb->name;
1482 rmb->table_idx = NULL;
1483 rmb->init_locals = mb->init_locals;
1484 rmb->skip_visibility = mb->skip_visibility;
1485 rmb->return_modreq = NULL;
1486 rmb->return_modopt = NULL;
1487 rmb->param_modreq = NULL;
1488 rmb->param_modopt = NULL;
1489 rmb->permissions = NULL;
1490 rmb->mhandle = mb->mhandle;
1497 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1499 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1500 MonoDynamicTable *table;
1504 if (!mb->override_method)
1507 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1509 alloc_table (table, table->rows);
1510 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1511 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1512 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1514 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1515 switch (mono_metadata_token_table (tok)) {
1516 case MONO_TABLE_MEMBERREF:
1517 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1519 case MONO_TABLE_METHOD:
1520 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1523 g_assert_not_reached ();
1525 values [MONO_METHODIMPL_DECLARATION] = tok;
1529 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1531 MonoDynamicTable *table;
1533 ReflectionMethodBuilder rmb;
1536 reflection_methodbuilder_from_method_builder (&rmb, mb);
1538 mono_image_basic_method (&rmb, assembly);
1539 mb->table_idx = *rmb.table_idx;
1541 if (mb->dll) { /* It's a P/Invoke method */
1543 /* map CharSet values to on-disk values */
1544 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1545 int extra_flags = mb->extra_flags;
1546 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1548 alloc_table (table, table->rows);
1549 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1551 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1552 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1554 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1556 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1557 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1558 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1559 table = &assembly->tables [MONO_TABLE_MODULEREF];
1561 alloc_table (table, table->rows);
1562 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1563 values [MONO_IMPLMAP_SCOPE] = table->rows;
1567 if (mb->generic_params) {
1568 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1569 table->rows += mono_array_length (mb->generic_params);
1570 alloc_table (table, table->rows);
1571 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1572 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1574 mono_image_get_generic_param_info (
1575 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1582 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1584 ReflectionMethodBuilder rmb;
1586 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1588 mono_image_basic_method (&rmb, assembly);
1589 mb->table_idx = *rmb.table_idx;
1593 type_get_fully_qualified_name (MonoType *type)
1595 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1599 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1603 klass = mono_class_from_mono_type (type);
1605 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1606 ta = klass->image->assembly;
1607 if (ta->dynamic || (ta == ass)) {
1608 if (klass->generic_class || klass->generic_container)
1609 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1612 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1615 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1618 #ifndef DISABLE_REFLECTION_EMIT
1620 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1625 if (!assembly->save)
1628 sigbuffer_init (&buf, 32);
1630 sigbuffer_add_value (&buf, 0x06);
1631 /* encode custom attributes before the type */
1632 /* FIXME: This should probably go in encode_type () */
1633 if (type->num_mods) {
1634 for (i = 0; i < type->num_mods; ++i) {
1635 if (type->modifiers [i].required)
1636 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1638 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1639 sigbuffer_add_value (&buf, type->modifiers [i].token);
1642 encode_type (assembly, type, &buf);
1643 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1644 sigbuffer_free (&buf);
1650 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1655 sigbuffer_init (&buf, 32);
1657 sigbuffer_add_value (&buf, 0x06);
1658 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1659 /* encode custom attributes before the type */
1660 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1661 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1662 sigbuffer_free (&buf);
1667 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1668 char blob_size [64];
1669 char *b = blob_size;
1672 guint32 idx = 0, len = 0, dummy = 0;
1674 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1675 guint32 fpa_double [2];
1680 p = buf = g_malloc (64);
1682 *ret_type = MONO_TYPE_CLASS;
1684 box_val = (char*)&dummy;
1686 box_val = ((char*)val) + sizeof (MonoObject);
1687 *ret_type = val->vtable->klass->byval_arg.type;
1690 switch (*ret_type) {
1691 case MONO_TYPE_BOOLEAN:
1696 case MONO_TYPE_CHAR:
1713 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1714 fpa_p = (guint32*)box_val;
1715 fpa_double [0] = fpa_p [1];
1716 fpa_double [1] = fpa_p [0];
1717 box_val = (char*)fpa_double;
1721 case MONO_TYPE_VALUETYPE:
1722 if (val->vtable->klass->enumtype) {
1723 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1726 g_error ("we can't encode valuetypes");
1727 case MONO_TYPE_CLASS:
1729 case MONO_TYPE_STRING: {
1730 MonoString *str = (MonoString*)val;
1731 /* there is no signature */
1732 len = str->length * 2;
1733 mono_metadata_encode_value (len, b, &b);
1734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1736 char *swapped = g_malloc (2 * mono_string_length (str));
1737 const char *p = (const char*)mono_string_chars (str);
1739 swap_with_size (swapped, p, 2, mono_string_length (str));
1740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1744 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1750 case MONO_TYPE_GENERICINST:
1751 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1754 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1757 /* there is no signature */
1758 mono_metadata_encode_value (len, b, &b);
1759 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1760 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1761 swap_with_size (blob_size, box_val, len, 1);
1762 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1764 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1772 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1777 sigbuffer_init (&buf, 32);
1779 sigbuffer_add_value (&buf, minfo->type);
1781 switch (minfo->type) {
1782 case MONO_NATIVE_BYVALTSTR:
1783 case MONO_NATIVE_BYVALARRAY:
1784 sigbuffer_add_value (&buf, minfo->count);
1786 case MONO_NATIVE_LPARRAY:
1787 if (minfo->eltype || minfo->has_size) {
1788 sigbuffer_add_value (&buf, minfo->eltype);
1789 if (minfo->has_size) {
1790 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1791 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1793 /* LAMESPEC: ElemMult is undocumented */
1794 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1798 case MONO_NATIVE_SAFEARRAY:
1800 sigbuffer_add_value (&buf, minfo->eltype);
1802 case MONO_NATIVE_CUSTOM:
1804 str = mono_string_to_utf8 (minfo->guid);
1806 sigbuffer_add_value (&buf, len);
1807 sigbuffer_add_mem (&buf, str, len);
1810 sigbuffer_add_value (&buf, 0);
1812 /* native type name */
1813 sigbuffer_add_value (&buf, 0);
1814 /* custom marshaler type name */
1815 if (minfo->marshaltype || minfo->marshaltyperef) {
1816 if (minfo->marshaltyperef)
1817 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1819 str = mono_string_to_utf8 (minfo->marshaltype);
1821 sigbuffer_add_value (&buf, len);
1822 sigbuffer_add_mem (&buf, str, len);
1825 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1826 sigbuffer_add_value (&buf, 0);
1828 if (minfo->mcookie) {
1829 str = mono_string_to_utf8 (minfo->mcookie);
1831 sigbuffer_add_value (&buf, len);
1832 sigbuffer_add_mem (&buf, str, len);
1835 sigbuffer_add_value (&buf, 0);
1841 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1842 sigbuffer_free (&buf);
1847 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1849 MonoDynamicTable *table;
1852 /* maybe this fixup should be done in the C# code */
1853 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1854 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1855 table = &assembly->tables [MONO_TABLE_FIELD];
1856 fb->table_idx = table->next_idx ++;
1857 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1858 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1859 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1860 values [MONO_FIELD_FLAGS] = fb->attrs;
1861 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1863 if (fb->offset != -1) {
1864 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1866 alloc_table (table, table->rows);
1867 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1868 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1869 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1871 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1872 guint32 field_type = 0;
1873 table = &assembly->tables [MONO_TABLE_CONSTANT];
1875 alloc_table (table, table->rows);
1876 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1877 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1878 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1879 values [MONO_CONSTANT_TYPE] = field_type;
1880 values [MONO_CONSTANT_PADDING] = 0;
1882 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1884 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1886 alloc_table (table, table->rows);
1887 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1888 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1890 * We store it in the code section because it's simpler for now.
1893 if (mono_array_length (fb->rva_data) >= 10)
1894 stream_data_align (&assembly->code);
1895 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1897 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1898 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1900 if (fb->marshal_info) {
1901 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1903 alloc_table (table, table->rows);
1904 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1905 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1906 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1911 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1914 guint32 nparams = 0;
1915 MonoReflectionMethodBuilder *mb = fb->get_method;
1916 MonoReflectionMethodBuilder *smb = fb->set_method;
1919 if (mb && mb->parameters)
1920 nparams = mono_array_length (mb->parameters);
1921 if (!mb && smb && smb->parameters)
1922 nparams = mono_array_length (smb->parameters) - 1;
1923 sigbuffer_init (&buf, 32);
1924 sigbuffer_add_byte (&buf, 0x08);
1925 sigbuffer_add_value (&buf, nparams);
1927 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1928 for (i = 0; i < nparams; ++i) {
1929 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1930 encode_reflection_type (assembly, pt, &buf);
1932 } else if (smb && smb->parameters) {
1933 /* the property type is the last param */
1934 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1935 for (i = 0; i < nparams; ++i) {
1936 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1937 encode_reflection_type (assembly, pt, &buf);
1940 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1943 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1944 sigbuffer_free (&buf);
1949 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1951 MonoDynamicTable *table;
1953 guint num_methods = 0;
1957 * we need to set things in the following tables:
1958 * PROPERTYMAP (info already filled in _get_type_info ())
1959 * PROPERTY (rows already preallocated in _get_type_info ())
1960 * METHOD (method info already done with the generic method code)
1963 table = &assembly->tables [MONO_TABLE_PROPERTY];
1964 pb->table_idx = table->next_idx ++;
1965 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1966 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1967 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1968 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1970 /* FIXME: we still don't handle 'other' methods */
1971 if (pb->get_method) num_methods ++;
1972 if (pb->set_method) num_methods ++;
1974 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1975 table->rows += num_methods;
1976 alloc_table (table, table->rows);
1978 if (pb->get_method) {
1979 semaidx = table->next_idx ++;
1980 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1981 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1982 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1983 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1985 if (pb->set_method) {
1986 semaidx = table->next_idx ++;
1987 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1988 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1989 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1990 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1995 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1997 MonoDynamicTable *table;
1999 guint num_methods = 0;
2003 * we need to set things in the following tables:
2004 * EVENTMAP (info already filled in _get_type_info ())
2005 * EVENT (rows already preallocated in _get_type_info ())
2006 * METHOD (method info already done with the generic method code)
2009 table = &assembly->tables [MONO_TABLE_EVENT];
2010 eb->table_idx = table->next_idx ++;
2011 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2012 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2013 values [MONO_EVENT_FLAGS] = eb->attrs;
2014 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2017 * FIXME: we still don't handle 'other' methods
2019 if (eb->add_method) num_methods ++;
2020 if (eb->remove_method) num_methods ++;
2021 if (eb->raise_method) num_methods ++;
2023 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2024 table->rows += num_methods;
2025 alloc_table (table, table->rows);
2027 if (eb->add_method) {
2028 semaidx = table->next_idx ++;
2029 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2030 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2031 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2032 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2034 if (eb->remove_method) {
2035 semaidx = table->next_idx ++;
2036 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2037 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2038 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2039 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2041 if (eb->raise_method) {
2042 semaidx = table->next_idx ++;
2043 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2044 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2045 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2046 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2051 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2053 MonoDynamicTable *table;
2054 guint32 num_constraints, i;
2058 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2059 num_constraints = gparam->iface_constraints ?
2060 mono_array_length (gparam->iface_constraints) : 0;
2061 table->rows += num_constraints;
2062 if (gparam->base_type)
2064 alloc_table (table, table->rows);
2066 if (gparam->base_type) {
2067 table_idx = table->next_idx ++;
2068 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2070 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2071 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2072 assembly, mono_reflection_type_get_handle (gparam->base_type));
2075 for (i = 0; i < num_constraints; i++) {
2076 MonoReflectionType *constraint = mono_array_get (
2077 gparam->iface_constraints, gpointer, i);
2079 table_idx = table->next_idx ++;
2080 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2082 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2083 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2084 assembly, mono_reflection_type_get_handle (constraint));
2089 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2091 GenericParamTableEntry *entry;
2094 * The GenericParam table must be sorted according to the `owner' field.
2095 * We need to do this sorting prior to writing the GenericParamConstraint
2096 * table, since we have to use the final GenericParam table indices there
2097 * and they must also be sorted.
2100 entry = g_new0 (GenericParamTableEntry, 1);
2101 entry->owner = owner;
2102 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2103 MOVING_GC_REGISTER (&entry->gparam);
2104 entry->gparam = gparam;
2106 g_ptr_array_add (assembly->gen_params, entry);
2110 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2112 MonoDynamicTable *table;
2113 MonoGenericParam *param;
2117 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2118 table_idx = table->next_idx ++;
2119 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2121 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2123 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2124 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2125 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2126 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2128 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2130 encode_constraints (entry->gparam, table_idx, assembly);
2134 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2136 MonoDynamicTable *table;
2139 guint32 cols [MONO_ASSEMBLY_SIZE];
2143 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2146 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2147 table = &assembly->tables [MONO_TABLE_MODULEREF];
2148 token = table->next_idx ++;
2150 alloc_table (table, table->rows);
2151 values = table->values + token * MONO_MODULEREF_SIZE;
2152 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2154 token <<= MONO_RESOLTION_SCOPE_BITS;
2155 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2156 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2161 if (image->assembly->dynamic)
2163 memset (cols, 0, sizeof (cols));
2165 /* image->assembly->image is the manifest module */
2166 image = image->assembly->image;
2167 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2170 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2171 token = table->next_idx ++;
2173 alloc_table (table, table->rows);
2174 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2175 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2176 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2177 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2178 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2179 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2180 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2181 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2182 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2184 if (strcmp ("", image->assembly->aname.culture)) {
2185 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2186 image->assembly->aname.culture);
2189 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2190 guchar pubtoken [9];
2192 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2193 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2195 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2197 token <<= MONO_RESOLTION_SCOPE_BITS;
2198 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2199 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2204 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2206 MonoDynamicTable *table;
2211 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2214 sigbuffer_init (&buf, 32);
2215 switch (type->type) {
2216 case MONO_TYPE_FNPTR:
2218 case MONO_TYPE_SZARRAY:
2219 case MONO_TYPE_ARRAY:
2221 case MONO_TYPE_MVAR:
2222 case MONO_TYPE_GENERICINST:
2223 encode_type (assembly, type, &buf);
2225 case MONO_TYPE_CLASS:
2226 case MONO_TYPE_VALUETYPE: {
2227 MonoClass *k = mono_class_from_mono_type (type);
2228 if (!k || !k->generic_container) {
2229 sigbuffer_free (&buf);
2232 encode_type (assembly, type, &buf);
2236 sigbuffer_free (&buf);
2240 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2241 if (assembly->save) {
2242 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2243 alloc_table (table, table->rows + 1);
2244 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2245 values [MONO_TYPESPEC_SIGNATURE] = token;
2247 sigbuffer_free (&buf);
2249 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2250 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2256 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2258 MonoDynamicTable *table;
2260 guint32 token, scope, enclosing;
2263 /* if the type requires a typespec, we must try that first*/
2264 if (try_typespec && (token = create_typespec (assembly, type)))
2266 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2269 klass = mono_class_from_mono_type (type);
2271 klass = mono_class_from_mono_type (type);
2274 * If it's in the same module and not a generic type parameter:
2276 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2277 (type->type != MONO_TYPE_MVAR)) {
2278 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2279 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2280 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2284 if (klass->nested_in) {
2285 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2286 /* get the typeref idx of the enclosing type */
2287 enclosing >>= MONO_TYPEDEFORREF_BITS;
2288 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2290 scope = resolution_scope_from_image (assembly, klass->image);
2292 table = &assembly->tables [MONO_TABLE_TYPEREF];
2293 if (assembly->save) {
2294 alloc_table (table, table->rows + 1);
2295 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2296 values [MONO_TYPEREF_SCOPE] = scope;
2297 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2298 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2300 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2301 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2303 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2308 * Despite the name, we handle also TypeSpec (with the above helper).
2311 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2313 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2316 #ifndef DISABLE_REFLECTION_EMIT
2318 * Insert a memberef row into the metadata: the token that point to the memberref
2319 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2320 * mono_image_get_fieldref_token()).
2321 * The sig param is an index to an already built signature.
2324 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2326 MonoDynamicTable *table;
2328 guint32 token, pclass;
2331 parent = mono_image_typedef_or_ref (assembly, type);
2332 switch (parent & MONO_TYPEDEFORREF_MASK) {
2333 case MONO_TYPEDEFORREF_TYPEREF:
2334 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2336 case MONO_TYPEDEFORREF_TYPESPEC:
2337 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2339 case MONO_TYPEDEFORREF_TYPEDEF:
2340 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2343 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2346 /* extract the index */
2347 parent >>= MONO_TYPEDEFORREF_BITS;
2349 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2351 if (assembly->save) {
2352 alloc_table (table, table->rows + 1);
2353 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2354 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2355 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2356 values [MONO_MEMBERREF_SIGNATURE] = sig;
2359 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2366 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2369 MonoMethodSignature *sig;
2371 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2373 if (create_typespec) {
2374 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2379 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2380 if (token && !create_typespec)
2383 g_assert (!method->is_inflated);
2386 * A methodref signature can't contain an unmanaged calling convention.
2388 sig = mono_metadata_signature_dup (mono_method_signature (method));
2389 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2390 sig->call_convention = MONO_CALL_DEFAULT;
2391 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2392 method->name, method_encode_signature (assembly, sig));
2394 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2397 if (create_typespec) {
2398 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2399 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2400 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2402 if (assembly->save) {
2405 alloc_table (table, table->rows + 1);
2406 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2407 values [MONO_METHODSPEC_METHOD] = token;
2408 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2411 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2413 /*methodspec and memberef tokens are diferent, */
2414 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2421 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2424 ReflectionMethodBuilder rmb;
2427 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2431 name = mono_string_to_utf8 (method->name);
2432 reflection_methodbuilder_from_method_builder (&rmb, method);
2435 * A methodref signature can't contain an unmanaged calling convention.
2436 * Since some flags are encoded as part of call_conv, we need to check against it.
2438 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2439 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2440 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2441 name, method_builder_encode_signature (assembly, &rmb));
2444 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2449 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2450 const gchar *name, guint32 sig)
2452 MonoDynamicTable *table;
2456 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2458 if (assembly->save) {
2459 alloc_table (table, table->rows + 1);
2460 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2461 values [MONO_MEMBERREF_CLASS] = original;
2462 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2463 values [MONO_MEMBERREF_SIGNATURE] = sig;
2466 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2473 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2477 guint32 nparams = mono_array_length (mb->generic_params);
2480 if (!assembly->save)
2483 sigbuffer_init (&buf, 32);
2485 sigbuffer_add_value (&buf, 0xa);
2486 sigbuffer_add_value (&buf, nparams);
2488 for (i = 0; i < nparams; i++) {
2489 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2490 sigbuffer_add_value (&buf, i);
2493 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2494 sigbuffer_free (&buf);
2499 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2501 MonoDynamicTable *table;
2503 guint32 token, mtoken = 0;
2505 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2509 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2511 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2512 switch (mono_metadata_token_table (mtoken)) {
2513 case MONO_TABLE_MEMBERREF:
2514 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2516 case MONO_TABLE_METHOD:
2517 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2520 g_assert_not_reached ();
2523 if (assembly->save) {
2524 alloc_table (table, table->rows + 1);
2525 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2526 values [MONO_METHODSPEC_METHOD] = mtoken;
2527 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2530 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2533 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2538 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2542 if (mb->generic_params && create_methodspec)
2543 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2545 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2549 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2550 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2555 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2558 ReflectionMethodBuilder rmb;
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2565 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2567 name = mono_string_to_utf8 (rmb.name);
2568 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2569 name, method_builder_encode_signature (assembly, &rmb));
2572 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2578 is_field_on_inst (MonoClassField *field)
2580 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2584 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2587 get_field_on_inst_generic_type (MonoClassField *field)
2589 MonoDynamicGenericClass *dgclass;
2592 g_assert (is_field_on_inst (field));
2594 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2595 field_index = field - dgclass->fields;
2597 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2598 return dgclass->field_generic_types [field_index];
2601 #ifndef DISABLE_REFLECTION_EMIT
2603 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2607 MonoClassField *field;
2609 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2612 g_assert (f->field->parent);
2615 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2616 int index = field - field->parent->fields;
2617 type = field->parent->generic_class->container_class->fields [index].type;
2619 if (is_field_on_inst (f->field))
2620 type = get_field_on_inst_generic_type (f->field);
2622 type = f->field->type;
2624 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2625 mono_field_get_name (f->field),
2626 fieldref_encode_signature (assembly, type));
2627 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2632 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2636 MonoGenericClass *gclass;
2637 MonoDynamicGenericClass *dgclass;
2638 MonoReflectionFieldBuilder *fb = f->fb;
2642 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2645 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2646 klass = mono_class_from_mono_type (type);
2647 gclass = type->data.generic_class;
2648 g_assert (gclass->is_dynamic);
2649 dgclass = (MonoDynamicGenericClass *) gclass;
2651 name = mono_string_to_utf8 (fb->name);
2652 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2653 field_encode_signature (assembly, fb));
2655 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2660 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2664 MonoGenericClass *gclass;
2665 MonoDynamicGenericClass *dgclass;
2666 MonoReflectionCtorBuilder *cb = c->cb;
2667 ReflectionMethodBuilder rmb;
2671 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2673 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2676 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2677 klass = mono_class_from_mono_type (type);
2678 gclass = type->data.generic_class;
2679 g_assert (gclass->is_dynamic);
2680 dgclass = (MonoDynamicGenericClass *) gclass;
2682 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2684 name = mono_string_to_utf8 (rmb.name);
2686 sig = method_builder_encode_signature (assembly, &rmb);
2688 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2691 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2696 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2699 MonoGenericContext tmp_context;
2700 MonoType **type_argv;
2701 MonoGenericInst *ginst;
2702 MonoMethod *method, *inflated;
2705 method = inflate_method (m->inst, (MonoObject*)m->mb);
2707 klass = method->klass;
2709 if (method->is_inflated)
2710 method = ((MonoMethodInflated *) method)->declaring;
2712 count = mono_array_length (m->method_args);
2714 type_argv = g_new0 (MonoType *, count);
2715 for (i = 0; i < count; i++) {
2716 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2717 type_argv [i] = mono_reflection_type_get_handle (garg);
2719 ginst = mono_metadata_get_generic_inst (count, type_argv);
2722 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2723 tmp_context.method_inst = ginst;
2725 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2730 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2734 MonoGenericClass *gclass;
2735 MonoReflectionMethodBuilder *mb = m->mb;
2736 ReflectionMethodBuilder rmb;
2740 if (m->method_args) {
2741 MonoMethod *inflated;
2743 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2744 if (create_methodspec)
2745 token = mono_image_get_methodspec_token (assembly, inflated);
2747 token = mono_image_get_inflated_method_token (assembly, inflated);
2751 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2754 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2755 klass = mono_class_from_mono_type (type);
2756 gclass = type->data.generic_class;
2757 g_assert (gclass->is_dynamic);
2759 reflection_methodbuilder_from_method_builder (&rmb, mb);
2761 name = mono_string_to_utf8 (rmb.name);
2763 sig = method_builder_encode_signature (assembly, &rmb);
2765 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2768 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2773 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2777 guint32 nparams = context->method_inst->type_argc;
2780 if (!assembly->save)
2783 sigbuffer_init (&buf, 32);
2785 * FIXME: vararg, explicit_this, differenc call_conv values...
2787 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2788 sigbuffer_add_value (&buf, nparams);
2790 for (i = 0; i < nparams; i++)
2791 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2793 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2794 sigbuffer_free (&buf);
2799 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2801 MonoDynamicTable *table;
2803 guint32 token, mtoken = 0, sig;
2804 MonoMethodInflated *imethod;
2805 MonoMethod *declaring;
2807 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2809 g_assert (method->is_inflated);
2810 imethod = (MonoMethodInflated *) method;
2811 declaring = imethod->declaring;
2813 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2814 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2816 if (!mono_method_signature (declaring)->generic_param_count)
2819 switch (mono_metadata_token_table (mtoken)) {
2820 case MONO_TABLE_MEMBERREF:
2821 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2823 case MONO_TABLE_METHOD:
2824 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2827 g_assert_not_reached ();
2830 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2832 if (assembly->save) {
2833 alloc_table (table, table->rows + 1);
2834 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2835 values [MONO_METHODSPEC_METHOD] = mtoken;
2836 values [MONO_METHODSPEC_SIGNATURE] = sig;
2839 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2846 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2848 MonoMethodInflated *imethod;
2851 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2855 g_assert (method->is_inflated);
2856 imethod = (MonoMethodInflated *) method;
2858 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2859 token = method_encode_methodspec (assembly, method);
2861 guint32 sig = method_encode_signature (
2862 assembly, mono_method_signature (imethod->declaring));
2863 token = mono_image_get_memberref_token (
2864 assembly, &method->klass->byval_arg, method->name, sig);
2867 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2872 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2874 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2877 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2878 token = mono_image_get_memberref_token (
2879 assembly, &m->klass->byval_arg, m->name, sig);
2885 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2887 MonoDynamicTable *table;
2896 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2897 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2898 * Because of this, we must not insert it into the `typeref' hash table.
2900 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2901 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2905 sigbuffer_init (&buf, 32);
2907 g_assert (tb->generic_params);
2908 klass = mono_class_from_mono_type (type);
2910 if (tb->generic_container)
2911 mono_reflection_create_generic_class (tb);
2913 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2914 g_assert (klass->generic_container);
2915 sigbuffer_add_value (&buf, klass->byval_arg.type);
2916 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2918 count = mono_array_length (tb->generic_params);
2919 sigbuffer_add_value (&buf, count);
2920 for (i = 0; i < count; i++) {
2921 MonoReflectionGenericParam *gparam;
2923 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2925 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
2928 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2930 if (assembly->save) {
2931 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2932 alloc_table (table, table->rows + 1);
2933 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2934 values [MONO_TYPESPEC_SIGNATURE] = token;
2936 sigbuffer_free (&buf);
2938 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2939 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2945 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2948 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2950 int i, count, len, pos;
2955 count += mono_array_length (modreq);
2957 count += mono_array_length (modopt);
2960 return mono_metadata_type_dup (NULL, type);
2962 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
2964 memcpy (t, type, MONO_SIZEOF_TYPE);
2966 t->num_mods = count;
2969 for (i = 0; i < mono_array_length (modreq); ++i) {
2970 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
2971 t->modifiers [pos].required = 1;
2972 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2977 for (i = 0; i < mono_array_length (modopt); ++i) {
2978 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
2979 t->modifiers [pos].required = 0;
2980 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2989 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2991 MonoDynamicTable *table;
2993 MonoType *custom = NULL;
2995 guint32 token, pclass, parent, sig;
2998 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
3002 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3003 name = mono_string_to_utf8 (fb->name);
3005 /* fb->type does not include the custom modifiers */
3006 /* FIXME: We should do this in one place when a fieldbuilder is created */
3007 if (fb->modreq || fb->modopt) {
3008 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3009 sig = fieldref_encode_signature (assembly, custom);
3012 sig = fieldref_encode_signature (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3015 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3016 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3018 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3019 parent >>= MONO_TYPEDEFORREF_BITS;
3021 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3023 if (assembly->save) {
3024 alloc_table (table, table->rows + 1);
3025 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3026 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3027 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3028 values [MONO_MEMBERREF_SIGNATURE] = sig;
3031 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3033 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3039 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3046 if (!assembly->save)
3049 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3050 g_assert (helper->type == 2);
3052 if (helper->arguments)
3053 nargs = mono_array_length (helper->arguments);
3057 size = 10 + (nargs * 10);
3059 sigbuffer_init (&buf, 32);
3061 /* Encode calling convention */
3062 /* Change Any to Standard */
3063 if ((helper->call_conv & 0x03) == 0x03)
3064 helper->call_conv = 0x01;
3065 /* explicit_this implies has_this */
3066 if (helper->call_conv & 0x40)
3067 helper->call_conv &= 0x20;
3069 if (helper->call_conv == 0) { /* Unmanaged */
3070 idx = helper->unmanaged_call_conv - 1;
3073 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3074 if (helper->call_conv & 0x02) /* varargs */
3078 sigbuffer_add_byte (&buf, idx);
3079 sigbuffer_add_value (&buf, nargs);
3080 encode_reflection_type (assembly, helper->return_type, &buf);
3081 for (i = 0; i < nargs; ++i) {
3082 MonoArray *modreqs = NULL;
3083 MonoArray *modopts = NULL;
3084 MonoReflectionType *pt;
3086 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3087 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3088 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3089 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3091 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3092 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3093 encode_reflection_type (assembly, pt, &buf);
3095 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3096 sigbuffer_free (&buf);
3102 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3105 MonoDynamicTable *table;
3108 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3109 idx = table->next_idx ++;
3111 alloc_table (table, table->rows);
3112 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3114 values [MONO_STAND_ALONE_SIGNATURE] =
3115 mono_reflection_encode_sighelper (assembly, helper);
3121 reflection_cc_to_file (int call_conv) {
3122 switch (call_conv & 0x3) {
3124 case 1: return MONO_CALL_DEFAULT;
3125 case 2: return MONO_CALL_VARARG;
3127 g_assert_not_reached ();
3131 #endif /* !DISABLE_REFLECTION_EMIT */
3135 MonoMethodSignature *sig;
3140 #ifndef DISABLE_REFLECTION_EMIT
3142 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3147 MonoMethodSignature *sig;
3151 name = mono_string_to_utf8 (m->name);
3152 nparams = mono_array_length (m->parameters);
3153 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3155 sig->sentinelpos = -1;
3156 sig->call_convention = reflection_cc_to_file (m->call_conv);
3157 sig->param_count = nparams;
3158 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3159 mtype = mono_reflection_type_get_handle (m->parent);
3160 for (i = 0; i < nparams; ++i)
3161 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3163 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3165 if (strcmp (name, am->name) == 0 &&
3166 mono_metadata_type_equal (am->parent, mtype) &&
3167 mono_metadata_signature_equal (am->sig, sig)) {
3170 m->table_idx = am->token & 0xffffff;
3174 am = g_new0 (ArrayMethod, 1);
3178 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3179 method_encode_signature (assembly, sig));
3180 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3181 m->table_idx = am->token & 0xffffff;
3187 * Insert into the metadata tables all the info about the TypeBuilder tb.
3188 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3191 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3193 MonoDynamicTable *table;
3195 int i, is_object = 0, is_system = 0;
3198 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3199 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3200 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3201 n = mono_string_to_utf8 (tb->name);
3202 if (strcmp (n, "Object") == 0)
3204 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3206 n = mono_string_to_utf8 (tb->nspace);
3207 if (strcmp (n, "System") == 0)
3209 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3211 if (tb->parent && !(is_system && is_object) &&
3212 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3213 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3215 values [MONO_TYPEDEF_EXTENDS] = 0;
3217 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3218 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3221 * if we have explicitlayout or sequentiallayouts, output data in the
3222 * ClassLayout table.
3224 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3225 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3226 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3228 alloc_table (table, table->rows);
3229 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3230 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3231 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3232 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3235 /* handle interfaces */
3236 if (tb->interfaces) {
3237 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3239 table->rows += mono_array_length (tb->interfaces);
3240 alloc_table (table, table->rows);
3241 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3242 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3243 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3244 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3245 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3246 values += MONO_INTERFACEIMPL_SIZE;
3252 table = &assembly->tables [MONO_TABLE_FIELD];
3253 table->rows += tb->num_fields;
3254 alloc_table (table, table->rows);
3255 for (i = 0; i < tb->num_fields; ++i)
3256 mono_image_get_field_info (
3257 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3260 /* handle constructors */
3262 table = &assembly->tables [MONO_TABLE_METHOD];
3263 table->rows += mono_array_length (tb->ctors);
3264 alloc_table (table, table->rows);
3265 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3266 mono_image_get_ctor_info (domain,
3267 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3270 /* handle methods */
3272 table = &assembly->tables [MONO_TABLE_METHOD];
3273 table->rows += tb->num_methods;
3274 alloc_table (table, table->rows);
3275 for (i = 0; i < tb->num_methods; ++i)
3276 mono_image_get_method_info (
3277 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3280 /* Do the same with properties etc.. */
3281 if (tb->events && mono_array_length (tb->events)) {
3282 table = &assembly->tables [MONO_TABLE_EVENT];
3283 table->rows += mono_array_length (tb->events);
3284 alloc_table (table, table->rows);
3285 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3287 alloc_table (table, table->rows);
3288 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3289 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3290 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3291 for (i = 0; i < mono_array_length (tb->events); ++i)
3292 mono_image_get_event_info (
3293 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3295 if (tb->properties && mono_array_length (tb->properties)) {
3296 table = &assembly->tables [MONO_TABLE_PROPERTY];
3297 table->rows += mono_array_length (tb->properties);
3298 alloc_table (table, table->rows);
3299 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3301 alloc_table (table, table->rows);
3302 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3303 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3304 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3305 for (i = 0; i < mono_array_length (tb->properties); ++i)
3306 mono_image_get_property_info (
3307 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3310 /* handle generic parameters */
3311 if (tb->generic_params) {
3312 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3313 table->rows += mono_array_length (tb->generic_params);
3314 alloc_table (table, table->rows);
3315 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3316 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3318 mono_image_get_generic_param_info (
3319 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3323 mono_image_add_decl_security (assembly,
3324 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3327 MonoDynamicTable *ntable;
3329 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3330 ntable->rows += mono_array_length (tb->subtypes);
3331 alloc_table (ntable, ntable->rows);
3332 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3334 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3335 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3337 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3338 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3339 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3340 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3341 mono_string_to_utf8 (tb->name), tb->table_idx,
3342 ntable->next_idx, ntable->rows);*/
3343 values += MONO_NESTED_CLASS_SIZE;
3350 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3354 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3356 if (!type->subtypes)
3359 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3360 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3361 collect_types (types, subtype);
3366 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3368 if ((*type1)->table_idx < (*type2)->table_idx)
3371 if ((*type1)->table_idx > (*type2)->table_idx)
3378 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3383 for (i = 0; i < mono_array_length (pinfo); ++i) {
3384 MonoReflectionParamBuilder *pb;
3385 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3388 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3393 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3396 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3398 for (i = 0; i < tb->num_fields; ++i) {
3399 MonoReflectionFieldBuilder* fb;
3400 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3401 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3405 for (i = 0; i < mono_array_length (tb->events); ++i) {
3406 MonoReflectionEventBuilder* eb;
3407 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3408 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3411 if (tb->properties) {
3412 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3413 MonoReflectionPropertyBuilder* pb;
3414 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3415 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3419 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3420 MonoReflectionCtorBuilder* cb;
3421 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3422 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3423 params_add_cattrs (assembly, cb->pinfo);
3428 for (i = 0; i < tb->num_methods; ++i) {
3429 MonoReflectionMethodBuilder* mb;
3430 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3431 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3432 params_add_cattrs (assembly, mb->pinfo);
3437 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3438 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3443 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3447 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3449 if (moduleb->global_methods) {
3450 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3451 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3452 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3453 params_add_cattrs (assembly, mb->pinfo);
3457 if (moduleb->global_fields) {
3458 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3459 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3460 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3464 if (moduleb->types) {
3465 for (i = 0; i < moduleb->num_types; ++i)
3466 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3471 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3473 MonoDynamicTable *table;
3477 char *b = blob_size;
3480 table = &assembly->tables [MONO_TABLE_FILE];
3482 alloc_table (table, table->rows);
3483 values = table->values + table->next_idx * MONO_FILE_SIZE;
3484 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3485 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3486 if (module->image->dynamic) {
3487 /* This depends on the fact that the main module is emitted last */
3488 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3489 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3492 path = g_strdup (module->image->name);
3494 mono_sha1_get_digest_from_file (path, hash);
3497 mono_metadata_encode_value (20, b, &b);
3498 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3499 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3504 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3506 MonoDynamicTable *table;
3509 table = &assembly->tables [MONO_TABLE_MODULE];
3510 mb->table_idx = table->next_idx ++;
3511 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3512 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3515 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3516 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3517 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3518 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3522 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3523 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3525 MonoDynamicTable *table;
3529 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3530 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3533 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3535 alloc_table (table, table->rows);
3536 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3538 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3539 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3540 if (klass->nested_in)
3541 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3543 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3544 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3545 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3547 res = table->next_idx;
3551 /* Emit nested types */
3552 if (klass->ext && klass->ext->nested_classes) {
3555 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3556 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3563 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3564 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3569 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3571 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3573 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3574 parent_index, assembly);
3578 * We need to do this ourselves since klass->nested_classes is not set up.
3581 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3582 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3587 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3588 guint32 module_index, MonoDynamicImage *assembly)
3590 MonoImage *image = module->image;
3594 t = &image->tables [MONO_TABLE_TYPEDEF];
3596 for (i = 0; i < t->rows; ++i) {
3597 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3599 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3600 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3605 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3607 MonoDynamicTable *table;
3609 guint32 scope, idx, res, impl;
3610 gboolean forwarder = TRUE;
3612 if (klass->nested_in) {
3613 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3616 scope = resolution_scope_from_image (assembly, klass->image);
3617 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3618 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3619 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3622 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3625 alloc_table (table, table->rows);
3626 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3628 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3629 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3630 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3631 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3632 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3634 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3642 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3647 if (!assemblyb->type_forwarders)
3650 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3651 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3656 type = mono_reflection_type_get_handle (t);
3659 klass = mono_class_from_mono_type (type);
3661 add_exported_type (assemblyb, assembly, klass);
3665 #define align_pointer(base,p)\
3667 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3669 (p) += 4 - (__diff & 3);\
3673 compare_constants (const void *a, const void *b)
3675 const guint32 *a_values = a;
3676 const guint32 *b_values = b;
3677 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3681 compare_semantics (const void *a, const void *b)
3683 const guint32 *a_values = a;
3684 const guint32 *b_values = b;
3685 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3688 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3692 compare_custom_attrs (const void *a, const void *b)
3694 const guint32 *a_values = a;
3695 const guint32 *b_values = b;
3697 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3701 compare_field_marshal (const void *a, const void *b)
3703 const guint32 *a_values = a;
3704 const guint32 *b_values = b;
3706 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3710 compare_nested (const void *a, const void *b)
3712 const guint32 *a_values = a;
3713 const guint32 *b_values = b;
3715 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3719 compare_genericparam (const void *a, const void *b)
3721 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3722 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3724 if ((*b_entry)->owner == (*a_entry)->owner)
3726 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3727 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3729 return (*a_entry)->owner - (*b_entry)->owner;
3733 compare_declsecurity_attrs (const void *a, const void *b)
3735 const guint32 *a_values = a;
3736 const guint32 *b_values = b;
3738 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3742 compare_interface_impl (const void *a, const void *b)
3744 const guint32 *a_values = a;
3745 const guint32 *b_values = b;
3747 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3751 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3755 pad_heap (MonoDynamicStream *sh)
3757 if (sh->index & 3) {
3758 int sz = 4 - (sh->index & 3);
3759 memset (sh->data + sh->index, 0, sz);
3766 MonoDynamicStream *stream;
3770 * build_compressed_metadata() fills in the blob of data that represents the
3771 * raw metadata as it will be saved in the PE file. The five streams are output
3772 * and the metadata tables are comnpressed from the guint32 array representation,
3773 * to the compressed on-disk format.
3776 build_compressed_metadata (MonoDynamicImage *assembly)
3778 MonoDynamicTable *table;
3780 guint64 valid_mask = 0;
3781 guint64 sorted_mask;
3782 guint32 heapt_size = 0;
3783 guint32 meta_size = 256; /* allow for header and other stuff */
3784 guint32 table_offset;
3785 guint32 ntables = 0;
3791 struct StreamDesc stream_desc [5];
3793 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3794 for (i = 0; i < assembly->gen_params->len; i++){
3795 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3796 write_generic_param_entry (assembly, entry);
3799 stream_desc [0].name = "#~";
3800 stream_desc [0].stream = &assembly->tstream;
3801 stream_desc [1].name = "#Strings";
3802 stream_desc [1].stream = &assembly->sheap;
3803 stream_desc [2].name = "#US";
3804 stream_desc [2].stream = &assembly->us;
3805 stream_desc [3].name = "#Blob";
3806 stream_desc [3].stream = &assembly->blob;
3807 stream_desc [4].name = "#GUID";
3808 stream_desc [4].stream = &assembly->guid;
3810 /* tables that are sorted */
3811 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3812 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3813 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3814 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3815 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3816 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3817 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3819 /* Compute table sizes */
3820 /* the MonoImage has already been created in mono_image_basic_init() */
3821 meta = &assembly->image;
3823 /* sizes should be multiple of 4 */
3824 pad_heap (&assembly->blob);
3825 pad_heap (&assembly->guid);
3826 pad_heap (&assembly->sheap);
3827 pad_heap (&assembly->us);
3829 /* Setup the info used by compute_sizes () */
3830 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3831 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3832 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3834 meta_size += assembly->blob.index;
3835 meta_size += assembly->guid.index;
3836 meta_size += assembly->sheap.index;
3837 meta_size += assembly->us.index;
3839 for (i=0; i < MONO_TABLE_NUM; ++i)
3840 meta->tables [i].rows = assembly->tables [i].rows;
3842 for (i = 0; i < MONO_TABLE_NUM; i++){
3843 if (meta->tables [i].rows == 0)
3845 valid_mask |= (guint64)1 << i;
3847 meta->tables [i].row_size = mono_metadata_compute_size (
3848 meta, i, &meta->tables [i].size_bitfield);
3849 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3851 heapt_size += 24; /* #~ header size */
3852 heapt_size += ntables * 4;
3853 /* make multiple of 4 */
3856 meta_size += heapt_size;
3857 meta->raw_metadata = g_malloc0 (meta_size);
3858 p = (unsigned char*)meta->raw_metadata;
3859 /* the metadata signature */
3860 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3861 /* version numbers and 4 bytes reserved */
3862 int16val = (guint16*)p;
3863 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3864 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3866 /* version string */
3867 int32val = (guint32*)p;
3868 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3870 memcpy (p, meta->version, strlen (meta->version));
3871 p += GUINT32_FROM_LE (*int32val);
3872 align_pointer (meta->raw_metadata, p);
3873 int16val = (guint16*)p;
3874 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3875 *int16val = GUINT16_TO_LE (5); /* number of streams */
3879 * write the stream info.
3881 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3882 table_offset += 3; table_offset &= ~3;
3884 assembly->tstream.index = heapt_size;
3885 for (i = 0; i < 5; ++i) {
3886 int32val = (guint32*)p;
3887 stream_desc [i].stream->offset = table_offset;
3888 *int32val++ = GUINT32_TO_LE (table_offset);
3889 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3890 table_offset += GUINT32_FROM_LE (*int32val);
3891 table_offset += 3; table_offset &= ~3;
3893 strcpy ((char*)p, stream_desc [i].name);
3894 p += strlen (stream_desc [i].name) + 1;
3895 align_pointer (meta->raw_metadata, p);
3898 * now copy the data, the table stream header and contents goes first.
3900 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3901 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3902 int32val = (guint32*)p;
3903 *int32val = GUINT32_TO_LE (0); /* reserved */
3906 if (mono_framework_version () > 1) {
3907 *p++ = 2; /* version */
3910 *p++ = 1; /* version */
3914 if (meta->idx_string_wide)
3916 if (meta->idx_guid_wide)
3918 if (meta->idx_blob_wide)
3921 *p++ = 1; /* reserved */
3922 int64val = (guint64*)p;
3923 *int64val++ = GUINT64_TO_LE (valid_mask);
3924 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3926 int32val = (guint32*)p;
3927 for (i = 0; i < MONO_TABLE_NUM; i++){
3928 if (meta->tables [i].rows == 0)
3930 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3932 p = (unsigned char*)int32val;
3934 /* sort the tables that still need sorting */
3935 table = &assembly->tables [MONO_TABLE_CONSTANT];
3937 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3938 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3940 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3941 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3943 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3944 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3946 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3947 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3949 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3950 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3951 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3953 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3954 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3956 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3958 /* compress the tables */
3959 for (i = 0; i < MONO_TABLE_NUM; i++){
3962 guint32 bitfield = meta->tables [i].size_bitfield;
3963 if (!meta->tables [i].rows)
3965 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3966 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3967 meta->tables [i].base = (char*)p;
3968 for (row = 1; row <= meta->tables [i].rows; ++row) {
3969 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3970 for (col = 0; col < assembly->tables [i].columns; ++col) {
3971 switch (mono_metadata_table_size (bitfield, col)) {
3973 *p++ = values [col];
3976 *p++ = values [col] & 0xff;
3977 *p++ = (values [col] >> 8) & 0xff;
3980 *p++ = values [col] & 0xff;
3981 *p++ = (values [col] >> 8) & 0xff;
3982 *p++ = (values [col] >> 16) & 0xff;
3983 *p++ = (values [col] >> 24) & 0xff;
3986 g_assert_not_reached ();
3990 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3993 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3994 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3995 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3996 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3997 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3999 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4003 * Some tables in metadata need to be sorted according to some criteria, but
4004 * when methods and fields are first created with reflection, they may be assigned a token
4005 * that doesn't correspond to the final token they will get assigned after the sorting.
4006 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4007 * with the reflection objects that represent them. Once all the tables are set up, the
4008 * reflection objects will contains the correct table index. fixup_method() will fixup the
4009 * tokens for the method with ILGenerator @ilgen.
4012 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4014 guint32 code_idx = GPOINTER_TO_UINT (value);
4015 MonoReflectionILTokenInfo *iltoken;
4016 MonoReflectionFieldBuilder *field;
4017 MonoReflectionCtorBuilder *ctor;
4018 MonoReflectionMethodBuilder *method;
4019 MonoReflectionTypeBuilder *tb;
4020 MonoReflectionArrayMethod *am;
4022 unsigned char *target;
4024 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4025 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4026 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4027 switch (target [3]) {
4028 case MONO_TABLE_FIELD:
4029 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4030 field = (MonoReflectionFieldBuilder *)iltoken->member;
4031 idx = field->table_idx;
4032 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4033 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4034 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4036 g_assert_not_reached ();
4039 case MONO_TABLE_METHOD:
4040 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4041 method = (MonoReflectionMethodBuilder *)iltoken->member;
4042 idx = method->table_idx;
4043 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4044 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4045 idx = ctor->table_idx;
4046 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4047 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4048 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4049 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4051 g_assert_not_reached ();
4054 case MONO_TABLE_TYPEDEF:
4055 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4056 g_assert_not_reached ();
4057 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4058 idx = tb->table_idx;
4060 case MONO_TABLE_MEMBERREF:
4061 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4062 am = (MonoReflectionArrayMethod*)iltoken->member;
4063 idx = am->table_idx;
4064 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4065 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4066 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4067 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4068 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4069 g_assert (m->klass->generic_class || m->klass->generic_container);
4071 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4073 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4074 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4075 g_assert (is_field_on_inst (f));
4077 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4078 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4080 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4082 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4084 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4087 g_assert_not_reached ();
4090 case MONO_TABLE_METHODSPEC:
4091 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4092 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4093 g_assert (mono_method_signature (m)->generic_param_count);
4095 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4097 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4100 g_assert_not_reached ();
4104 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4106 target [0] = idx & 0xff;
4107 target [1] = (idx >> 8) & 0xff;
4108 target [2] = (idx >> 16) & 0xff;
4115 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4116 * value is not known when the table is emitted.
4119 fixup_cattrs (MonoDynamicImage *assembly)
4121 MonoDynamicTable *table;
4123 guint32 type, i, idx, token;
4126 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4128 for (i = 0; i < table->rows; ++i) {
4129 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4131 type = values [MONO_CUSTOM_ATTR_TYPE];
4132 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4133 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4134 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4135 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4138 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4139 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4140 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4141 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4148 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4150 MonoDynamicTable *table;
4153 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4155 alloc_table (table, table->rows);
4156 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4157 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4158 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4159 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4160 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4165 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4167 MonoDynamicTable *table;
4171 char *b = blob_size;
4173 guint32 idx, offset;
4175 if (rsrc->filename) {
4176 name = mono_string_to_utf8 (rsrc->filename);
4177 sname = g_path_get_basename (name);
4179 table = &assembly->tables [MONO_TABLE_FILE];
4181 alloc_table (table, table->rows);
4182 values = table->values + table->next_idx * MONO_FILE_SIZE;
4183 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4184 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4187 mono_sha1_get_digest_from_file (name, hash);
4188 mono_metadata_encode_value (20, b, &b);
4189 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4190 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4192 idx = table->next_idx++;
4194 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4200 data = mono_array_addr (rsrc->data, char, 0);
4201 len = mono_array_length (rsrc->data);
4207 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4208 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4209 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4210 mono_image_add_stream_data (&assembly->resources, data, len);
4214 * The entry should be emitted into the MANIFESTRESOURCE table of
4215 * the main module, but that needs to reference the FILE table
4216 * which isn't emitted yet.
4223 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4227 set_version_from_string (MonoString *version, guint32 *values)
4229 gchar *ver, *p, *str;
4232 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4233 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4234 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4235 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4238 ver = str = mono_string_to_utf8 (version);
4239 for (i = 0; i < 4; ++i) {
4240 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4246 /* handle Revision and Build */
4256 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4260 char *b = blob_size;
4265 len = mono_array_length (pkey);
4266 mono_metadata_encode_value (len, b, &b);
4267 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4268 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4270 assembly->public_key = g_malloc (len);
4271 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4272 assembly->public_key_len = len;
4274 /* Special case: check for ECMA key (16 bytes) */
4275 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4276 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4277 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4278 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4279 /* minimum key size (in 2.0) is 384 bits */
4280 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4282 /* FIXME - verifier */
4283 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4284 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4286 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4292 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4294 MonoDynamicTable *table;
4295 MonoDynamicImage *assembly;
4296 MonoReflectionAssemblyBuilder *assemblyb;
4300 guint32 module_index;
4302 assemblyb = moduleb->assemblyb;
4303 assembly = moduleb->dynamic_image;
4304 domain = mono_object_domain (assemblyb);
4306 /* Emit ASSEMBLY table */
4307 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4308 alloc_table (table, 1);
4309 values = table->values + MONO_ASSEMBLY_SIZE;
4310 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4311 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4312 if (assemblyb->culture) {
4313 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4315 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4317 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4318 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4319 set_version_from_string (assemblyb->version, values);
4321 /* Emit FILE + EXPORTED_TYPE table */
4323 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4325 MonoReflectionModuleBuilder *file_module =
4326 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4327 if (file_module != moduleb) {
4328 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4330 if (file_module->types) {
4331 for (j = 0; j < file_module->num_types; ++j) {
4332 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4333 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4338 if (assemblyb->loaded_modules) {
4339 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4340 MonoReflectionModule *file_module =
4341 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4342 mono_image_fill_file_table (domain, file_module, assembly);
4344 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4347 if (assemblyb->type_forwarders)
4348 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4350 /* Emit MANIFESTRESOURCE table */
4352 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4354 MonoReflectionModuleBuilder *file_module =
4355 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4356 /* The table for the main module is emitted later */
4357 if (file_module != moduleb) {
4359 if (file_module->resources) {
4360 int len = mono_array_length (file_module->resources);
4361 for (j = 0; j < len; ++j) {
4362 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4363 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4370 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4373 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4374 * for the modulebuilder @moduleb.
4375 * At the end of the process, method and field tokens are fixed up and the
4376 * on-disk compressed metadata representation is created.
4379 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4381 MonoDynamicTable *table;
4382 MonoDynamicImage *assembly;
4383 MonoReflectionAssemblyBuilder *assemblyb;
4389 assemblyb = moduleb->assemblyb;
4390 assembly = moduleb->dynamic_image;
4391 domain = mono_object_domain (assemblyb);
4393 if (assembly->text_rva)
4396 assembly->text_rva = START_TEXT_RVA;
4398 if (moduleb->is_main) {
4399 mono_image_emit_manifest (moduleb);
4402 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4403 table->rows = 1; /* .<Module> */
4405 alloc_table (table, table->rows);
4407 * Set the first entry.
4409 values = table->values + table->columns;
4410 values [MONO_TYPEDEF_FLAGS] = 0;
4411 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4412 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4413 values [MONO_TYPEDEF_EXTENDS] = 0;
4414 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4415 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4418 * handle global methods
4419 * FIXME: test what to do when global methods are defined in multiple modules.
4421 if (moduleb->global_methods) {
4422 table = &assembly->tables [MONO_TABLE_METHOD];
4423 table->rows += mono_array_length (moduleb->global_methods);
4424 alloc_table (table, table->rows);
4425 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4426 mono_image_get_method_info (
4427 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4429 if (moduleb->global_fields) {
4430 table = &assembly->tables [MONO_TABLE_FIELD];
4431 table->rows += mono_array_length (moduleb->global_fields);
4432 alloc_table (table, table->rows);
4433 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4434 mono_image_get_field_info (
4435 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4438 table = &assembly->tables [MONO_TABLE_MODULE];
4439 alloc_table (table, 1);
4440 mono_image_fill_module_table (domain, moduleb, assembly);
4442 /* Collect all types into a list sorted by their table_idx */
4443 types = g_ptr_array_new ();
4446 for (i = 0; i < moduleb->num_types; ++i) {
4447 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4448 collect_types (types, type);
4451 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4452 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4453 table->rows += types->len;
4454 alloc_table (table, table->rows);
4457 * Emit type names + namespaces at one place inside the string heap,
4458 * so load_class_names () needs to touch fewer pages.
4460 for (i = 0; i < types->len; ++i) {
4461 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4462 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4464 for (i = 0; i < types->len; ++i) {
4465 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4466 string_heap_insert_mstring (&assembly->sheap, tb->name);
4469 for (i = 0; i < types->len; ++i) {
4470 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4471 mono_image_get_type_info (domain, type, assembly);
4475 * table->rows is already set above and in mono_image_fill_module_table.
4477 /* add all the custom attributes at the end, once all the indexes are stable */
4478 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4480 /* CAS assembly permissions */
4481 if (assemblyb->permissions_minimum)
4482 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4483 if (assemblyb->permissions_optional)
4484 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4485 if (assemblyb->permissions_refused)
4486 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4488 module_add_cattrs (assembly, moduleb);
4491 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4493 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4494 * the final tokens and don't need another fixup pass. */
4496 if (moduleb->global_methods) {
4497 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4498 MonoReflectionMethodBuilder *mb = mono_array_get (
4499 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4500 mono_image_add_methodimpl (assembly, mb);
4504 for (i = 0; i < types->len; ++i) {
4505 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4506 if (type->methods) {
4507 for (j = 0; j < type->num_methods; ++j) {
4508 MonoReflectionMethodBuilder *mb = mono_array_get (
4509 type->methods, MonoReflectionMethodBuilder*, j);
4511 mono_image_add_methodimpl (assembly, mb);
4516 g_ptr_array_free (types, TRUE);
4518 fixup_cattrs (assembly);
4521 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4524 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4526 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4529 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4533 guint32 import_lookup_table;
4537 guint32 import_address_table_rva;
4545 #ifndef DISABLE_REFLECTION_EMIT
4548 * mono_image_insert_string:
4549 * @module: module builder object
4552 * Insert @str into the user string stream of @module.
4555 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4557 MonoDynamicImage *assembly;
4562 MONO_ARCH_SAVE_REGS;
4564 if (!module->dynamic_image)
4565 mono_image_module_basic_init (module);
4567 assembly = module->dynamic_image;
4569 if (assembly->save) {
4570 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4571 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4572 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4574 char *swapped = g_malloc (2 * mono_string_length (str));
4575 const char *p = (const char*)mono_string_chars (str);
4577 swap_with_size (swapped, p, 2, mono_string_length (str));
4578 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4582 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4584 mono_image_add_stream_data (&assembly->us, "", 1);
4586 idx = assembly->us.index ++;
4589 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4591 return MONO_TOKEN_STRING | idx;
4595 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4600 klass = obj->vtable->klass;
4601 if (strcmp (klass->name, "MonoMethod") == 0) {
4602 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4603 MonoMethodSignature *sig, *old;
4604 guint32 sig_token, parent;
4607 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4609 nargs = mono_array_length (opt_param_types);
4610 old = mono_method_signature (method);
4611 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4613 sig->hasthis = old->hasthis;
4614 sig->explicit_this = old->explicit_this;
4615 sig->call_convention = old->call_convention;
4616 sig->generic_param_count = old->generic_param_count;
4617 sig->param_count = old->param_count + nargs;
4618 sig->sentinelpos = old->param_count;
4619 sig->ret = old->ret;
4621 for (i = 0; i < old->param_count; i++)
4622 sig->params [i] = old->params [i];
4624 for (i = 0; i < nargs; i++) {
4625 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4626 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4629 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4630 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4631 parent >>= MONO_TYPEDEFORREF_BITS;
4633 parent <<= MONO_MEMBERREF_PARENT_BITS;
4634 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4636 sig_token = method_encode_signature (assembly, sig);
4637 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4638 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4639 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4640 ReflectionMethodBuilder rmb;
4641 guint32 parent, sig;
4644 reflection_methodbuilder_from_method_builder (&rmb, mb);
4645 rmb.opt_types = opt_param_types;
4647 sig = method_builder_encode_signature (assembly, &rmb);
4649 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4650 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4652 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4653 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4655 name = mono_string_to_utf8 (rmb.name);
4656 token = mono_image_get_varargs_method_token (
4657 assembly, parent, name, sig);
4660 g_error ("requested method token for %s\n", klass->name);
4667 * mono_image_create_token:
4668 * @assembly: a dynamic assembly
4670 * @register_token: Whenever to register the token in the assembly->tokens hash.
4672 * Get a token to insert in the IL code stream for the given MemberInfo.
4673 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4674 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4678 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4679 gboolean create_methodspec, gboolean register_token)
4684 klass = obj->vtable->klass;
4686 /* Check for user defined reflection objects */
4687 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4688 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4689 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4691 if (strcmp (klass->name, "MethodBuilder") == 0) {
4692 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4693 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4695 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4696 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4698 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4699 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4700 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4701 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4702 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4704 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4705 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4707 token = mono_image_get_ctorbuilder_token (assembly, mb);
4708 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4709 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4710 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4711 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4712 if (tb->generic_params) {
4713 token = mono_image_get_generic_field_token (assembly, fb);
4715 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4717 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4718 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4719 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4720 } else if (strcmp (klass->name, "MonoType") == 0) {
4721 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4722 MonoClass *mc = mono_class_from_mono_type (type);
4723 token = mono_metadata_token_from_dor (
4724 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4725 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4726 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4727 token = mono_metadata_token_from_dor (
4728 mono_image_typedef_or_ref (assembly, type));
4729 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4730 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4731 token = mono_metadata_token_from_dor (
4732 mono_image_typedef_or_ref (assembly, type));
4733 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4734 strcmp (klass->name, "MonoMethod") == 0 ||
4735 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4736 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4737 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4738 if (m->method->is_inflated) {
4739 if (create_methodspec)
4740 token = mono_image_get_methodspec_token (assembly, m->method);
4742 token = mono_image_get_inflated_method_token (assembly, m->method);
4743 } else if ((m->method->klass->image == &assembly->image) &&
4744 !m->method->klass->generic_class) {
4745 static guint32 method_table_idx = 0xffffff;
4746 if (m->method->klass->wastypebuilder) {
4747 /* we use the same token as the one that was assigned
4748 * to the Methodbuilder.
4749 * FIXME: do the equivalent for Fields.
4751 token = m->method->token;
4754 * Each token should have a unique index, but the indexes are
4755 * assigned by managed code, so we don't know about them. An
4756 * easy solution is to count backwards...
4758 method_table_idx --;
4759 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4762 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4764 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4765 } else if (strcmp (klass->name, "MonoField") == 0) {
4766 MonoReflectionField *f = (MonoReflectionField *)obj;
4767 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4768 static guint32 field_table_idx = 0xffffff;
4770 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4772 token = mono_image_get_fieldref_token (assembly, f);
4774 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4775 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4776 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4777 token = mono_image_get_array_token (assembly, m);
4778 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4779 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4780 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4781 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4782 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4783 token = mono_metadata_token_from_dor (
4784 mono_image_typedef_or_ref (assembly, type));
4785 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4786 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4787 token = mono_image_get_field_on_inst_token (assembly, f);
4788 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4789 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4790 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4791 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4792 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4793 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4794 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4795 MonoReflectionType *type = (MonoReflectionType *)obj;
4796 token = mono_metadata_token_from_dor (
4797 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4799 g_error ("requested token for %s\n", klass->name);
4803 mono_image_register_token (assembly, token, obj);
4809 * mono_image_register_token:
4811 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4812 * the Module.ResolveXXXToken () methods to work.
4815 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4817 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4819 /* There could be multiple MethodInfo objects with the same token */
4820 //g_assert (prev == obj);
4822 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4826 static MonoDynamicImage*
4827 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4829 static const guchar entrycode [16] = {0xff, 0x25, 0};
4830 MonoDynamicImage *image;
4833 const char *version;
4835 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4836 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4838 version = mono_get_runtime_info ()->runtime_version;
4841 image = GC_MALLOC (sizeof (MonoDynamicImage));
4843 image = g_new0 (MonoDynamicImage, 1);
4846 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4848 /*g_print ("created image %p\n", image);*/
4849 /* keep in sync with image.c */
4850 image->image.name = assembly_name;
4851 image->image.assembly_name = image->image.name; /* they may be different */
4852 image->image.module_name = module_name;
4853 image->image.version = g_strdup (version);
4854 image->image.md_version_major = 1;
4855 image->image.md_version_minor = 1;
4856 image->image.dynamic = TRUE;
4858 image->image.references = g_new0 (MonoAssembly*, 1);
4859 image->image.references [0] = NULL;
4861 mono_image_init (&image->image);
4863 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4864 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4865 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4866 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4867 image->handleref = g_hash_table_new (NULL, NULL);
4868 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4869 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4870 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4871 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4872 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4873 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4874 image->gen_params = g_ptr_array_new ();
4876 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4877 string_heap_init (&image->sheap);
4878 mono_image_add_stream_data (&image->us, "", 1);
4879 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4880 /* import tables... */
4881 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4882 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4883 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4884 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4885 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4886 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4887 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4888 stream_data_align (&image->code);
4890 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4892 for (i=0; i < MONO_TABLE_NUM; ++i) {
4893 image->tables [i].next_idx = 1;
4894 image->tables [i].columns = table_sizes [i];
4897 image->image.assembly = (MonoAssembly*)assembly;
4898 image->run = assembly->run;
4899 image->save = assembly->save;
4900 image->pe_kind = 0x1; /* ILOnly */
4901 image->machine = 0x14c; /* I386 */
4903 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4910 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4916 mono_dynamic_image_free (MonoDynamicImage *image)
4918 MonoDynamicImage *di = image;
4923 mono_g_hash_table_destroy (di->methodspec);
4925 g_hash_table_destroy (di->typespec);
4927 g_hash_table_destroy (di->typeref);
4929 g_hash_table_destroy (di->handleref);
4931 mono_g_hash_table_destroy (di->tokens);
4932 if (di->generic_def_objects)
4933 mono_g_hash_table_destroy (di->generic_def_objects);
4934 if (di->blob_cache) {
4935 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4936 g_hash_table_destroy (di->blob_cache);
4938 if (di->standalonesig_cache)
4939 g_hash_table_destroy (di->standalonesig_cache);
4940 for (list = di->array_methods; list; list = list->next) {
4941 ArrayMethod *am = (ArrayMethod *)list->data;
4946 g_list_free (di->array_methods);
4947 if (di->gen_params) {
4948 for (i = 0; i < di->gen_params->len; i++) {
4949 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4950 if (entry->gparam->type.type) {
4951 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4952 g_free ((char*)mono_generic_param_info (param)->name);
4957 g_ptr_array_free (di->gen_params, TRUE);
4959 if (di->token_fixups)
4960 mono_g_hash_table_destroy (di->token_fixups);
4961 if (di->method_to_table_idx)
4962 g_hash_table_destroy (di->method_to_table_idx);
4963 if (di->field_to_table_idx)
4964 g_hash_table_destroy (di->field_to_table_idx);
4965 if (di->method_aux_hash)
4966 g_hash_table_destroy (di->method_aux_hash);
4967 g_free (di->strong_name);
4968 g_free (di->win32_res);
4970 g_free (di->public_key);
4972 /*g_print ("string heap destroy for image %p\n", di);*/
4973 mono_dynamic_stream_reset (&di->sheap);
4974 mono_dynamic_stream_reset (&di->code);
4975 mono_dynamic_stream_reset (&di->resources);
4976 mono_dynamic_stream_reset (&di->us);
4977 mono_dynamic_stream_reset (&di->blob);
4978 mono_dynamic_stream_reset (&di->tstream);
4979 mono_dynamic_stream_reset (&di->guid);
4980 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4981 g_free (di->tables [i].values);
4985 #ifndef DISABLE_REFLECTION_EMIT
4988 * mono_image_basic_init:
4989 * @assembly: an assembly builder object
4991 * Create the MonoImage that represents the assembly builder and setup some
4992 * of the helper hash table and the basic metadata streams.
4995 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4997 MonoDynamicAssembly *assembly;
4998 MonoDynamicImage *image;
4999 MonoDomain *domain = mono_object_domain (assemblyb);
5001 MONO_ARCH_SAVE_REGS;
5003 if (assemblyb->dynamic_assembly)
5007 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5009 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5012 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5014 assembly->assembly.ref_count = 1;
5015 assembly->assembly.dynamic = TRUE;
5016 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5017 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5018 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5019 if (assemblyb->culture)
5020 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5022 assembly->assembly.aname.culture = g_strdup ("");
5024 if (assemblyb->version) {
5025 char *vstr = mono_string_to_utf8 (assemblyb->version);
5026 char **version = g_strsplit (vstr, ".", 4);
5027 char **parts = version;
5028 assembly->assembly.aname.major = atoi (*parts++);
5029 assembly->assembly.aname.minor = atoi (*parts++);
5030 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5031 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5033 g_strfreev (version);
5036 assembly->assembly.aname.major = 0;
5037 assembly->assembly.aname.minor = 0;
5038 assembly->assembly.aname.build = 0;
5039 assembly->assembly.aname.revision = 0;
5042 assembly->run = assemblyb->access != 2;
5043 assembly->save = assemblyb->access != 1;
5045 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5046 image->initial_image = TRUE;
5047 assembly->assembly.aname.name = image->image.name;
5048 assembly->assembly.image = &image->image;
5049 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5050 /* -1 to correct for the trailing NULL byte */
5051 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5052 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5054 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5057 mono_domain_assemblies_lock (domain);
5058 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5059 mono_domain_assemblies_unlock (domain);
5061 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5063 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5065 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5068 #endif /* !DISABLE_REFLECTION_EMIT */
5070 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5073 calc_section_size (MonoDynamicImage *assembly)
5077 /* alignment constraints */
5078 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5079 g_assert ((assembly->code.index % 4) == 0);
5080 assembly->meta_size += 3;
5081 assembly->meta_size &= ~3;
5082 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5083 g_assert ((assembly->resources.index % 4) == 0);
5085 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5086 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5089 if (assembly->win32_res) {
5090 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5092 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5093 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5097 assembly->sections [MONO_SECTION_RELOC].size = 12;
5098 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5108 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5112 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5114 ResTreeNode *t1 = (ResTreeNode*)a;
5115 ResTreeNode *t2 = (ResTreeNode*)b;
5117 return t1->id - t2->id;
5121 * resource_tree_create:
5123 * Organize the resources into a resource tree.
5125 static ResTreeNode *
5126 resource_tree_create (MonoArray *win32_resources)
5128 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5132 tree = g_new0 (ResTreeNode, 1);
5134 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5135 MonoReflectionWin32Resource *win32_res =
5136 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5140 /* FIXME: BUG: this stores managed references in unmanaged memory */
5141 lang_node = g_new0 (ResTreeNode, 1);
5142 lang_node->id = win32_res->lang_id;
5143 lang_node->win32_res = win32_res;
5145 /* Create type node if neccesary */
5147 for (l = tree->children; l; l = l->next)
5148 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5149 type_node = (ResTreeNode*)l->data;
5154 type_node = g_new0 (ResTreeNode, 1);
5155 type_node->id = win32_res->res_type;
5158 * The resource types have to be sorted otherwise
5159 * Windows Explorer can't display the version information.
5161 tree->children = g_slist_insert_sorted (tree->children,
5162 type_node, resource_tree_compare_by_id);
5165 /* Create res node if neccesary */
5167 for (l = type_node->children; l; l = l->next)
5168 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5169 res_node = (ResTreeNode*)l->data;
5174 res_node = g_new0 (ResTreeNode, 1);
5175 res_node->id = win32_res->res_id;
5176 type_node->children = g_slist_append (type_node->children, res_node);
5179 res_node->children = g_slist_append (res_node->children, lang_node);
5186 * resource_tree_encode:
5188 * Encode the resource tree into the format used in the PE file.
5191 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5194 MonoPEResourceDir dir;
5195 MonoPEResourceDirEntry dir_entry;
5196 MonoPEResourceDataEntry data_entry;
5198 guint32 res_id_entries;
5201 * For the format of the resource directory, see the article
5202 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5206 memset (&dir, 0, sizeof (dir));
5207 memset (&dir_entry, 0, sizeof (dir_entry));
5208 memset (&data_entry, 0, sizeof (data_entry));
5210 g_assert (sizeof (dir) == 16);
5211 g_assert (sizeof (dir_entry) == 8);
5212 g_assert (sizeof (data_entry) == 16);
5214 node->offset = p - begin;
5216 /* IMAGE_RESOURCE_DIRECTORY */
5217 res_id_entries = g_slist_length (node->children);
5218 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5220 memcpy (p, &dir, sizeof (dir));
5223 /* Reserve space for entries */
5225 p += sizeof (dir_entry) * res_id_entries;
5227 /* Write children */
5228 for (l = node->children; l; l = l->next) {
5229 ResTreeNode *child = (ResTreeNode*)l->data;
5231 if (child->win32_res) {
5234 child->offset = p - begin;
5236 /* IMAGE_RESOURCE_DATA_ENTRY */
5237 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5238 size = mono_array_length (child->win32_res->res_data);
5239 data_entry.rde_size = GUINT32_TO_LE (size);
5241 memcpy (p, &data_entry, sizeof (data_entry));
5242 p += sizeof (data_entry);
5244 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5247 resource_tree_encode (child, begin, p, &p);
5251 /* IMAGE_RESOURCE_ENTRY */
5252 for (l = node->children; l; l = l->next) {
5253 ResTreeNode *child = (ResTreeNode*)l->data;
5255 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5256 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5258 memcpy (entries, &dir_entry, sizeof (dir_entry));
5259 entries += sizeof (dir_entry);
5266 resource_tree_free (ResTreeNode * node)
5269 for (list = node->children; list; list = list->next)
5270 resource_tree_free ((ResTreeNode*)list->data);
5271 g_slist_free(node->children);
5276 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5281 MonoReflectionWin32Resource *win32_res;
5284 if (!assemblyb->win32_resources)
5288 * Resources are stored in a three level tree inside the PE file.
5289 * - level one contains a node for each type of resource
5290 * - level two contains a node for each resource
5291 * - level three contains a node for each instance of a resource for a
5292 * specific language.
5295 tree = resource_tree_create (assemblyb->win32_resources);
5297 /* Estimate the size of the encoded tree */
5299 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5300 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5301 size += mono_array_length (win32_res->res_data);
5303 /* Directory structure */
5304 size += mono_array_length (assemblyb->win32_resources) * 256;
5305 p = buf = g_malloc (size);
5307 resource_tree_encode (tree, p, p, &p);
5309 g_assert (p - buf <= size);
5311 assembly->win32_res = g_malloc (p - buf);
5312 assembly->win32_res_size = p - buf;
5313 memcpy (assembly->win32_res, buf, p - buf);
5316 resource_tree_free (tree);
5320 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5322 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5325 p += sizeof (MonoPEResourceDir);
5326 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5327 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5328 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5329 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5330 fixup_resource_directory (res_section, child, rva);
5332 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5333 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5336 p += sizeof (MonoPEResourceDirEntry);
5341 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5344 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5345 g_error ("WriteFile returned %d\n", GetLastError ());
5349 * mono_image_create_pefile:
5350 * @mb: a module builder object
5352 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5353 * assembly->pefile where it can be easily retrieved later in chunks.
5356 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5358 MonoMSDOSHeader *msdos;
5359 MonoDotNetHeader *header;
5360 MonoSectionTable *section;
5361 MonoCLIHeader *cli_header;
5362 guint32 size, image_size, virtual_base, text_offset;
5363 guint32 header_start, section_start, file_offset, virtual_offset;
5364 MonoDynamicImage *assembly;
5365 MonoReflectionAssemblyBuilder *assemblyb;
5366 MonoDynamicStream pefile_stream = {0};
5367 MonoDynamicStream *pefile = &pefile_stream;
5369 guint32 *rva, value;
5371 static const unsigned char msheader[] = {
5372 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5373 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5376 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5377 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5378 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5379 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5382 assemblyb = mb->assemblyb;
5384 mono_image_basic_init (assemblyb);
5385 assembly = mb->dynamic_image;
5387 assembly->pe_kind = assemblyb->pe_kind;
5388 assembly->machine = assemblyb->machine;
5389 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5390 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5392 mono_image_build_metadata (mb);
5394 if (mb->is_main && assemblyb->resources) {
5395 int len = mono_array_length (assemblyb->resources);
5396 for (i = 0; i < len; ++i)
5397 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5400 if (mb->resources) {
5401 int len = mono_array_length (mb->resources);
5402 for (i = 0; i < len; ++i)
5403 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5406 build_compressed_metadata (assembly);
5409 assembly_add_win32_resources (assembly, assemblyb);
5411 nsections = calc_section_size (assembly);
5413 /* The DOS header and stub */
5414 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5415 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5417 /* the dotnet header */
5418 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5420 /* the section tables */
5421 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5423 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5424 virtual_offset = VIRT_ALIGN;
5427 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5428 if (!assembly->sections [i].size)
5431 file_offset += FILE_ALIGN - 1;
5432 file_offset &= ~(FILE_ALIGN - 1);
5433 virtual_offset += VIRT_ALIGN - 1;
5434 virtual_offset &= ~(VIRT_ALIGN - 1);
5436 assembly->sections [i].offset = file_offset;
5437 assembly->sections [i].rva = virtual_offset;
5439 file_offset += assembly->sections [i].size;
5440 virtual_offset += assembly->sections [i].size;
5441 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5444 file_offset += FILE_ALIGN - 1;
5445 file_offset &= ~(FILE_ALIGN - 1);
5447 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5449 /* back-patch info */
5450 msdos = (MonoMSDOSHeader*)pefile->data;
5451 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5453 header = (MonoDotNetHeader*)(pefile->data + header_start);
5454 header->pesig [0] = 'P';
5455 header->pesig [1] = 'E';
5457 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5458 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5459 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5460 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5461 if (assemblyb->pekind == 1) {
5463 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5466 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5469 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5471 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5472 header->pe.pe_major = 6;
5473 header->pe.pe_minor = 0;
5474 size = assembly->sections [MONO_SECTION_TEXT].size;
5475 size += FILE_ALIGN - 1;
5476 size &= ~(FILE_ALIGN - 1);
5477 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5478 size = assembly->sections [MONO_SECTION_RSRC].size;
5479 size += FILE_ALIGN - 1;
5480 size &= ~(FILE_ALIGN - 1);
5481 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5482 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5483 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5484 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5485 /* pe_rva_entry_point always at the beginning of the text section */
5486 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5488 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5489 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5490 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5491 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5492 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5493 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5494 size = section_start;
5495 size += FILE_ALIGN - 1;
5496 size &= ~(FILE_ALIGN - 1);
5497 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5499 size += VIRT_ALIGN - 1;
5500 size &= ~(VIRT_ALIGN - 1);
5501 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5504 // Translate the PEFileKind value to the value expected by the Windows loader
5510 // PEFileKinds.Dll == 1
5511 // PEFileKinds.ConsoleApplication == 2
5512 // PEFileKinds.WindowApplication == 3
5515 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5516 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5518 if (assemblyb->pekind == 3)
5523 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5525 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5526 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5527 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5528 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5529 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5530 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5532 /* fill data directory entries */
5534 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5535 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5537 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5538 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5540 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5541 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5542 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5543 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5544 /* patch entrypoint name */
5545 if (assemblyb->pekind == 1)
5546 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5548 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5549 /* patch imported function RVA name */
5550 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5551 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5553 /* the import table */
5554 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5555 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5556 /* patch imported dll RVA name and other entries in the dir */
5557 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5558 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5559 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5560 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5561 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5562 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5564 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5565 value = (assembly->text_rva + assembly->imp_names_offset);
5566 *p++ = (value) & 0xff;
5567 *p++ = (value >> 8) & (0xff);
5568 *p++ = (value >> 16) & (0xff);
5569 *p++ = (value >> 24) & (0xff);
5571 /* the CLI header info */
5572 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5573 cli_header->ch_size = GUINT32_FROM_LE (72);
5574 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5575 if (mono_framework_version () > 1)
5576 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5578 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5579 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5580 if (assemblyb->entry_point) {
5581 guint32 table_idx = 0;
5582 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5583 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5584 table_idx = methodb->table_idx;
5586 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5588 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5590 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5592 /* The embedded managed resources */
5593 text_offset = assembly->text_rva + assembly->code.index;
5594 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5595 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5596 text_offset += assembly->resources.index;
5597 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5598 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5599 text_offset += assembly->meta_size;
5600 if (assembly->strong_name_size) {
5601 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5602 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5603 text_offset += assembly->strong_name_size;
5606 /* write the section tables and section content */
5607 section = (MonoSectionTable*)(pefile->data + section_start);
5608 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5609 static const char section_names [][7] = {
5610 ".text", ".rsrc", ".reloc"
5612 if (!assembly->sections [i].size)
5614 strcpy (section->st_name, section_names [i]);
5615 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5616 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5617 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5618 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5619 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5620 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5621 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5625 checked_write_file (file, pefile->data, pefile->index);
5627 mono_dynamic_stream_reset (pefile);
5629 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5630 if (!assembly->sections [i].size)
5633 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5634 g_error ("SetFilePointer returned %d\n", GetLastError ());
5637 case MONO_SECTION_TEXT:
5638 /* patch entry point */
5639 p = (guchar*)(assembly->code.data + 2);
5640 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5641 *p++ = (value) & 0xff;
5642 *p++ = (value >> 8) & 0xff;
5643 *p++ = (value >> 16) & 0xff;
5644 *p++ = (value >> 24) & 0xff;
5646 checked_write_file (file, assembly->code.data, assembly->code.index);
5647 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5648 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5649 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5652 g_free (assembly->image.raw_metadata);
5654 case MONO_SECTION_RELOC: {
5658 guint16 type_and_offset;
5662 g_assert (sizeof (reloc) == 12);
5664 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5665 reloc.block_size = GUINT32_FROM_LE (12);
5668 * the entrypoint is always at the start of the text section
5669 * 3 is IMAGE_REL_BASED_HIGHLOW
5670 * 2 is patch_size_rva - text_rva
5672 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5675 checked_write_file (file, &reloc, sizeof (reloc));
5679 case MONO_SECTION_RSRC:
5680 if (assembly->win32_res) {
5682 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5683 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5684 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5688 g_assert_not_reached ();
5692 /* check that the file is properly padded */
5693 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5694 g_error ("SetFilePointer returned %d\n", GetLastError ());
5695 if (! SetEndOfFile (file))
5696 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5698 mono_dynamic_stream_reset (&assembly->code);
5699 mono_dynamic_stream_reset (&assembly->us);
5700 mono_dynamic_stream_reset (&assembly->blob);
5701 mono_dynamic_stream_reset (&assembly->guid);
5702 mono_dynamic_stream_reset (&assembly->sheap);
5704 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5705 g_hash_table_destroy (assembly->blob_cache);
5706 assembly->blob_cache = NULL;
5709 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5712 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5714 g_assert_not_reached ();
5717 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5719 #ifndef DISABLE_REFLECTION_EMIT
5721 MonoReflectionModule *
5722 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5726 MonoImageOpenStatus status;
5727 MonoDynamicAssembly *assembly;
5728 guint32 module_count;
5729 MonoImage **new_modules;
5730 gboolean *new_modules_loaded;
5732 name = mono_string_to_utf8 (fileName);
5734 image = mono_image_open (name, &status);
5737 if (status == MONO_IMAGE_ERROR_ERRNO)
5738 exc = mono_get_exception_file_not_found (fileName);
5740 exc = mono_get_exception_bad_image_format (name);
5742 mono_raise_exception (exc);
5747 assembly = ab->dynamic_assembly;
5748 image->assembly = (MonoAssembly*)assembly;
5750 module_count = image->assembly->image->module_count;
5751 new_modules = g_new0 (MonoImage *, module_count + 1);
5752 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5754 if (image->assembly->image->modules)
5755 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5756 if (image->assembly->image->modules_loaded)
5757 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5758 new_modules [module_count] = image;
5759 new_modules_loaded [module_count] = TRUE;
5760 mono_image_addref (image);
5762 g_free (image->assembly->image->modules);
5763 image->assembly->image->modules = new_modules;
5764 image->assembly->image->modules_loaded = new_modules_loaded;
5765 image->assembly->image->module_count ++;
5767 mono_assembly_load_references (image, &status);
5769 mono_image_close (image);
5770 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5773 return mono_module_get_object (mono_domain_get (), image);
5776 #endif /* DISABLE_REFLECTION_EMIT */
5779 * We need to return always the same object for MethodInfo, FieldInfo etc..
5780 * but we need to consider the reflected type.
5781 * type uses a different hash, since it uses custom hash/equal functions.
5786 MonoClass *refclass;
5790 reflected_equal (gconstpointer a, gconstpointer b) {
5791 const ReflectedEntry *ea = a;
5792 const ReflectedEntry *eb = b;
5794 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5798 reflected_hash (gconstpointer a) {
5799 const ReflectedEntry *ea = a;
5800 return mono_aligned_addr_hash (ea->item);
5803 #define CHECK_OBJECT(t,p,k) \
5809 mono_domain_lock (domain); \
5810 if (!domain->refobject_hash) \
5811 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5812 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5813 mono_domain_unlock (domain); \
5816 mono_domain_unlock (domain); \
5819 #ifdef HAVE_BOEHM_GC
5820 /* ReflectedEntry doesn't need to be GC tracked */
5821 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5822 #define FREE_REFENTRY(entry) g_free ((entry))
5823 #define REFENTRY_REQUIRES_CLEANUP
5825 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5827 #define FREE_REFENTRY(entry)
5830 #define CACHE_OBJECT(t,p,o,k) \
5833 ReflectedEntry pe; \
5835 pe.refclass = (k); \
5836 mono_domain_lock (domain); \
5837 if (!domain->refobject_hash) \
5838 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5839 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5841 ReflectedEntry *e = ALLOC_REFENTRY; \
5843 e->refclass = (k); \
5844 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5847 mono_domain_unlock (domain); \
5852 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5854 mono_domain_lock (domain);
5855 if (domain->refobject_hash) {
5857 gpointer orig_pe, orig_value;
5860 pe.refclass = klass;
5861 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5862 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5863 FREE_REFENTRY (orig_pe);
5866 mono_domain_unlock (domain);
5869 #ifdef REFENTRY_REQUIRES_CLEANUP
5871 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5873 FREE_REFENTRY (key);
5878 mono_reflection_cleanup_domain (MonoDomain *domain)
5880 if (domain->refobject_hash) {
5881 /*let's avoid scanning the whole hashtable if not needed*/
5882 #ifdef REFENTRY_REQUIRES_CLEANUP
5883 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5885 mono_g_hash_table_destroy (domain->refobject_hash);
5886 domain->refobject_hash = NULL;
5890 #ifndef DISABLE_REFLECTION_EMIT
5892 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5894 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5898 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5900 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5904 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5906 MonoDynamicImage *image = moduleb->dynamic_image;
5907 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5910 MonoImage **new_modules;
5913 * FIXME: we already created an image in mono_image_basic_init (), but
5914 * we don't know which module it belongs to, since that is only
5915 * determined at assembly save time.
5917 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5918 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5920 moduleb->module.image = &image->image;
5921 moduleb->dynamic_image = image;
5922 register_module (mono_object_domain (moduleb), moduleb, image);
5924 /* register the module with the assembly */
5925 ass = ab->dynamic_assembly->assembly.image;
5926 module_count = ass->module_count;
5927 new_modules = g_new0 (MonoImage *, module_count + 1);
5930 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5931 new_modules [module_count] = &image->image;
5932 mono_image_addref (&image->image);
5934 g_free (ass->modules);
5935 ass->modules = new_modules;
5936 ass->module_count ++;
5941 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
5943 MonoDynamicImage *image = moduleb->dynamic_image;
5945 g_assert (type->type);
5946 image->wrappers_type = mono_class_from_mono_type (type->type);
5952 * mono_assembly_get_object:
5953 * @domain: an app domain
5954 * @assembly: an assembly
5956 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5958 MonoReflectionAssembly*
5959 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5961 static MonoClass *System_Reflection_Assembly;
5962 MonoReflectionAssembly *res;
5964 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5965 if (!System_Reflection_Assembly)
5966 System_Reflection_Assembly = mono_class_from_name (
5967 mono_defaults.corlib, "System.Reflection", "Assembly");
5968 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5969 res->assembly = assembly;
5971 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5976 MonoReflectionModule*
5977 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5979 static MonoClass *System_Reflection_Module;
5980 MonoReflectionModule *res;
5983 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5984 if (!System_Reflection_Module)
5985 System_Reflection_Module = mono_class_from_name (
5986 mono_defaults.corlib, "System.Reflection", "Module");
5987 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5990 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5992 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5993 basename = g_path_get_basename (image->name);
5994 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5995 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5999 if (image->assembly->image == image) {
6000 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6004 if (image->assembly->image->modules) {
6005 for (i = 0; i < image->assembly->image->module_count; i++) {
6006 if (image->assembly->image->modules [i] == image)
6007 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6009 g_assert (res->token);
6013 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6016 MonoReflectionModule*
6017 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6019 static MonoClass *System_Reflection_Module;
6020 MonoReflectionModule *res;
6021 MonoTableInfo *table;
6022 guint32 cols [MONO_FILE_SIZE];
6024 guint32 i, name_idx;
6027 if (!System_Reflection_Module)
6028 System_Reflection_Module = mono_class_from_name (
6029 mono_defaults.corlib, "System.Reflection", "Module");
6030 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6032 table = &image->tables [MONO_TABLE_FILE];
6033 g_assert (table_index < table->rows);
6034 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6037 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6038 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6040 /* Check whenever the row has a corresponding row in the moduleref table */
6041 table = &image->tables [MONO_TABLE_MODULEREF];
6042 for (i = 0; i < table->rows; ++i) {
6043 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6044 val = mono_metadata_string_heap (image, name_idx);
6045 if (strcmp (val, name) == 0)
6046 res->image = image->modules [i];
6049 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6050 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6051 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6052 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6053 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6059 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6061 if ((t1->type != t2->type) ||
6062 (t1->byref != t2->byref))
6066 case MONO_TYPE_VOID:
6067 case MONO_TYPE_BOOLEAN:
6068 case MONO_TYPE_CHAR:
6079 case MONO_TYPE_STRING:
6082 case MONO_TYPE_OBJECT:
6083 case MONO_TYPE_TYPEDBYREF:
6085 case MONO_TYPE_VALUETYPE:
6086 case MONO_TYPE_CLASS:
6087 case MONO_TYPE_SZARRAY:
6088 return t1->data.klass == t2->data.klass;
6090 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6091 case MONO_TYPE_ARRAY:
6092 if (t1->data.array->rank != t2->data.array->rank)
6094 return t1->data.array->eklass == t2->data.array->eklass;
6095 case MONO_TYPE_GENERICINST: {
6097 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6098 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6099 if (i1->type_argc != i2->type_argc)
6101 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6102 &t2->data.generic_class->container_class->byval_arg))
6104 /* FIXME: we should probably just compare the instance pointers directly. */
6105 for (i = 0; i < i1->type_argc; ++i) {
6106 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6112 case MONO_TYPE_MVAR:
6113 return t1->data.generic_param == t2->data.generic_param;
6115 g_error ("implement type compare for %0x!", t1->type);
6123 mymono_metadata_type_hash (MonoType *t1)
6129 hash |= t1->byref << 6; /* do not collide with t1->type values */
6131 case MONO_TYPE_VALUETYPE:
6132 case MONO_TYPE_CLASS:
6133 case MONO_TYPE_SZARRAY:
6134 /* check if the distribution is good enough */
6135 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6137 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6138 case MONO_TYPE_GENERICINST: {
6140 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6141 hash += g_str_hash (t1->data.generic_class->container_class->name);
6143 for (i = 0; i < inst->type_argc; ++i) {
6144 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6153 static MonoReflectionGenericClass*
6154 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6156 static MonoClass *System_Reflection_MonoGenericClass;
6157 MonoReflectionGenericClass *res;
6158 MonoClass *klass, *gklass;
6159 MonoGenericInst *ginst;
6160 MonoArray *type_args;
6163 if (!System_Reflection_MonoGenericClass) {
6164 System_Reflection_MonoGenericClass = mono_class_from_name (
6165 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6166 g_assert (System_Reflection_MonoGenericClass);
6169 klass = mono_class_from_mono_type (geninst);
6170 gklass = klass->generic_class->container_class;
6172 mono_class_init (klass);
6175 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6177 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6180 res->type.type = geninst;
6181 g_assert (gklass->reflection_info);
6182 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6183 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6185 ginst = klass->generic_class->context.class_inst;
6186 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6187 for (i = 0; i < ginst->type_argc; ++i)
6188 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6189 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6195 verify_safe_for_managed_space (MonoType *type)
6197 switch (type->type) {
6199 case MONO_TYPE_ARRAY:
6200 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6202 return verify_safe_for_managed_space (type->data.type);
6203 case MONO_TYPE_SZARRAY:
6204 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6205 case MONO_TYPE_GENERICINST: {
6206 MonoGenericInst *inst = type->data.generic_class->inst;
6210 for (i = 0; i < inst->type_argc; ++i)
6211 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6217 case MONO_TYPE_MVAR:
6224 * mono_type_get_object:
6225 * @domain: an app domain
6228 * Return an System.MonoType object representing the type @type.
6231 mono_type_get_object (MonoDomain *domain, MonoType *type)
6233 MonoReflectionType *res;
6234 MonoClass *klass = mono_class_from_mono_type (type);
6236 /*we must avoid using @type as it might have come
6237 * from a mono_metadata_type_dup and the caller
6238 * expects that is can be freed.
6239 * Using the right type from
6241 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6243 /* void is very common */
6244 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6245 return (MonoReflectionType*)domain->typeof_void;
6248 * If the vtable of the given class was already created, we can use
6249 * the MonoType from there and avoid all locking and hash table lookups.
6251 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6252 * that the resulting object is different.
6254 if (type == &klass->byval_arg && !klass->image->dynamic) {
6255 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6256 if (vtable && vtable->type)
6257 return vtable->type;
6260 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6261 mono_domain_lock (domain);
6262 if (!domain->type_hash)
6263 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6264 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6265 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6266 mono_domain_unlock (domain);
6267 mono_loader_unlock ();
6270 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6271 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6272 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6273 mono_g_hash_table_insert (domain->type_hash, type, res);
6274 mono_domain_unlock (domain);
6275 mono_loader_unlock ();
6279 if (!verify_safe_for_managed_space (type)) {
6280 mono_domain_unlock (domain);
6281 mono_loader_unlock ();
6282 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6285 if (klass->reflection_info && !klass->wastypebuilder) {
6286 /* g_assert_not_reached (); */
6287 /* should this be considered an error condition? */
6289 mono_domain_unlock (domain);
6290 mono_loader_unlock ();
6291 return klass->reflection_info;
6294 // FIXME: Get rid of this, do it in the icalls for Type
6295 mono_class_init (klass);
6297 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6299 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6302 mono_g_hash_table_insert (domain->type_hash, type, res);
6304 if (type->type == MONO_TYPE_VOID)
6305 domain->typeof_void = (MonoObject*)res;
6307 mono_domain_unlock (domain);
6308 mono_loader_unlock ();
6313 * mono_method_get_object:
6314 * @domain: an app domain
6316 * @refclass: the reflected type (can be NULL)
6318 * Return an System.Reflection.MonoMethod object representing the method @method.
6320 MonoReflectionMethod*
6321 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6324 * We use the same C representation for methods and constructors, but the type
6325 * name in C# is different.
6327 static MonoClass *System_Reflection_MonoMethod = NULL;
6328 static MonoClass *System_Reflection_MonoCMethod = NULL;
6329 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6330 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6332 MonoReflectionMethod *ret;
6334 if (method->is_inflated) {
6335 MonoReflectionGenericMethod *gret;
6337 refclass = method->klass;
6338 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6339 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6340 if (!System_Reflection_MonoGenericCMethod)
6341 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6342 klass = System_Reflection_MonoGenericCMethod;
6344 if (!System_Reflection_MonoGenericMethod)
6345 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6346 klass = System_Reflection_MonoGenericMethod;
6348 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6349 gret->method.method = method;
6350 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6351 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6352 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6356 refclass = method->klass;
6358 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6359 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6360 if (!System_Reflection_MonoCMethod)
6361 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6362 klass = System_Reflection_MonoCMethod;
6365 if (!System_Reflection_MonoMethod)
6366 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6367 klass = System_Reflection_MonoMethod;
6369 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6370 ret->method = method;
6371 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6372 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6376 * mono_method_clear_object:
6378 * Clear the cached reflection objects for the dynamic method METHOD.
6381 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6384 g_assert (method->dynamic);
6386 klass = method->klass;
6388 clear_cached_object (domain, method, klass);
6389 klass = klass->parent;
6391 /* Added by mono_param_get_objects () */
6392 clear_cached_object (domain, &(method->signature), NULL);
6393 klass = method->klass;
6395 clear_cached_object (domain, &(method->signature), klass);
6396 klass = klass->parent;
6401 * mono_field_get_object:
6402 * @domain: an app domain
6406 * Return an System.Reflection.MonoField object representing the field @field
6409 MonoReflectionField*
6410 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6412 MonoReflectionField *res;
6413 static MonoClass *monofield_klass;
6415 CHECK_OBJECT (MonoReflectionField *, field, klass);
6416 if (!monofield_klass)
6417 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6418 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6421 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6422 if (is_field_on_inst (field))
6423 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6425 res->attrs = field->type->attrs;
6426 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6427 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6431 * mono_property_get_object:
6432 * @domain: an app domain
6434 * @property: a property
6436 * Return an System.Reflection.MonoProperty object representing the property @property
6439 MonoReflectionProperty*
6440 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6442 MonoReflectionProperty *res;
6443 static MonoClass *monoproperty_klass;
6445 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6446 if (!monoproperty_klass)
6447 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6448 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6450 res->property = property;
6451 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6455 * mono_event_get_object:
6456 * @domain: an app domain
6460 * Return an System.Reflection.MonoEvent object representing the event @event
6463 MonoReflectionEvent*
6464 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6466 MonoReflectionEvent *res;
6467 MonoReflectionMonoEvent *mono_event;
6468 static MonoClass *monoevent_klass;
6470 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6471 if (!monoevent_klass)
6472 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6473 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6474 mono_event->klass = klass;
6475 mono_event->event = event;
6476 res = (MonoReflectionEvent*)mono_event;
6477 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6481 * mono_get_reflection_missing_object:
6482 * @domain: Domain where the object lives
6484 * Returns the System.Reflection.Missing.Value singleton object
6485 * (of type System.Reflection.Missing).
6487 * Used as the value for ParameterInfo.DefaultValue when Optional
6491 mono_get_reflection_missing_object (MonoDomain *domain)
6494 static MonoClassField *missing_value_field = NULL;
6496 if (!missing_value_field) {
6497 MonoClass *missing_klass;
6498 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6499 mono_class_init (missing_klass);
6500 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6501 g_assert (missing_value_field);
6503 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6509 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6512 *dbnull = mono_get_dbnull_object (domain);
6517 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6519 if (!*reflection_missing)
6520 *reflection_missing = mono_get_reflection_missing_object (domain);
6521 return *reflection_missing;
6525 * mono_param_get_objects:
6526 * @domain: an app domain
6529 * Return an System.Reflection.ParameterInfo array object representing the parameters
6530 * in the method @method.
6533 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6535 static MonoClass *System_Reflection_ParameterInfo;
6536 static MonoClass *System_Reflection_ParameterInfo_array;
6537 MonoArray *res = NULL;
6538 MonoReflectionMethod *member = NULL;
6539 MonoReflectionParameter *param = NULL;
6540 char **names, **blobs = NULL;
6541 guint32 *types = NULL;
6542 MonoType *type = NULL;
6543 MonoObject *dbnull = NULL;
6544 MonoObject *missing = NULL;
6545 MonoMarshalSpec **mspecs;
6546 MonoMethodSignature *sig;
6547 MonoVTable *pinfo_vtable;
6550 if (!System_Reflection_ParameterInfo_array) {
6553 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6554 mono_memory_barrier ();
6555 System_Reflection_ParameterInfo = klass;
6557 klass = mono_array_class_get (klass, 1);
6558 mono_memory_barrier ();
6559 System_Reflection_ParameterInfo_array = klass;
6562 if (!mono_method_signature (method)->param_count)
6563 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6565 /* Note: the cache is based on the address of the signature into the method
6566 * since we already cache MethodInfos with the method as keys.
6568 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6570 sig = mono_method_signature (method);
6571 member = mono_method_get_object (domain, method, refclass);
6572 names = g_new (char *, sig->param_count);
6573 mono_method_get_param_names (method, (const char **) names);
6575 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6576 mono_method_get_marshal_info (method, mspecs);
6578 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6579 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6580 for (i = 0; i < sig->param_count; ++i) {
6581 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6582 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6583 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6584 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6585 param->PositionImpl = i;
6586 param->AttrsImpl = sig->params [i]->attrs;
6588 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6589 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6590 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6592 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6596 blobs = g_new0 (char *, sig->param_count);
6597 types = g_new0 (guint32, sig->param_count);
6598 get_default_param_value_blobs (method, blobs, types);
6601 /* Build MonoType for the type from the Constant Table */
6603 type = g_new0 (MonoType, 1);
6604 type->type = types [i];
6605 type->data.klass = NULL;
6606 if (types [i] == MONO_TYPE_CLASS)
6607 type->data.klass = mono_defaults.object_class;
6608 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6609 /* For enums, types [i] contains the base type */
6611 type->type = MONO_TYPE_VALUETYPE;
6612 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6614 type->data.klass = mono_class_from_mono_type (type);
6616 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6618 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6619 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6620 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6621 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6623 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6629 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6631 mono_array_setref (res, i, param);
6638 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6640 mono_metadata_free_marshal_spec (mspecs [i]);
6643 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6647 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6649 return mono_param_get_objects_internal (domain, method, NULL);
6653 * mono_method_body_get_object:
6654 * @domain: an app domain
6657 * Return an System.Reflection.MethodBody object representing the method @method.
6659 MonoReflectionMethodBody*
6660 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6662 static MonoClass *System_Reflection_MethodBody = NULL;
6663 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6664 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6665 MonoReflectionMethodBody *ret;
6666 MonoMethodNormal *mn;
6667 MonoMethodHeader *header;
6668 guint32 method_rva, local_var_sig_token;
6670 unsigned char format, flags;
6673 if (!System_Reflection_MethodBody)
6674 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6675 if (!System_Reflection_LocalVariableInfo)
6676 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6677 if (!System_Reflection_ExceptionHandlingClause)
6678 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6680 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6682 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6683 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6684 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6685 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6687 mn = (MonoMethodNormal *)method;
6688 header = mono_method_get_header (method);
6690 /* Obtain local vars signature token */
6691 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6692 ptr = mono_image_rva_map (method->klass->image, method_rva);
6693 flags = *(const unsigned char *) ptr;
6694 format = flags & METHOD_HEADER_FORMAT_MASK;
6696 case METHOD_HEADER_TINY_FORMAT:
6697 case METHOD_HEADER_TINY_FORMAT1:
6698 local_var_sig_token = 0;
6700 case METHOD_HEADER_FAT_FORMAT:
6704 local_var_sig_token = read32 (ptr);
6707 g_assert_not_reached ();
6710 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6712 ret->init_locals = header->init_locals;
6713 ret->max_stack = header->max_stack;
6714 ret->local_var_sig_token = local_var_sig_token;
6715 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6716 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6719 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6720 for (i = 0; i < header->num_locals; ++i) {
6721 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6722 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6723 info->is_pinned = header->locals [i]->pinned;
6724 info->local_index = i;
6725 mono_array_setref (ret->locals, i, info);
6729 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6730 for (i = 0; i < header->num_clauses; ++i) {
6731 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6732 MonoExceptionClause *clause = &header->clauses [i];
6734 info->flags = clause->flags;
6735 info->try_offset = clause->try_offset;
6736 info->try_length = clause->try_len;
6737 info->handler_offset = clause->handler_offset;
6738 info->handler_length = clause->handler_len;
6739 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6740 info->filter_offset = clause->data.filter_offset;
6741 else if (clause->data.catch_class)
6742 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6744 mono_array_setref (ret->clauses, i, info);
6747 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6752 * mono_get_dbnull_object:
6753 * @domain: Domain where the object lives
6755 * Returns the System.DBNull.Value singleton object
6757 * Used as the value for ParameterInfo.DefaultValue
6760 mono_get_dbnull_object (MonoDomain *domain)
6763 static MonoClassField *dbnull_value_field = NULL;
6765 if (!dbnull_value_field) {
6766 MonoClass *dbnull_klass;
6767 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6768 mono_class_init (dbnull_klass);
6769 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6770 g_assert (dbnull_value_field);
6772 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6778 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6780 guint32 param_index, i, lastp, crow = 0;
6781 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6784 MonoClass *klass = method->klass;
6785 MonoImage *image = klass->image;
6786 MonoMethodSignature *methodsig = mono_method_signature (method);
6788 MonoTableInfo *constt;
6789 MonoTableInfo *methodt;
6790 MonoTableInfo *paramt;
6792 if (!methodsig->param_count)
6795 mono_class_init (klass);
6797 if (klass->image->dynamic) {
6798 MonoReflectionMethodAux *aux;
6799 if (method->is_inflated)
6800 method = ((MonoMethodInflated*)method)->declaring;
6801 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6802 if (aux && aux->param_defaults) {
6803 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6804 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6809 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6810 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6811 constt = &image->tables [MONO_TABLE_CONSTANT];
6813 idx = mono_method_get_index (method) - 1;
6814 g_assert (idx != -1);
6816 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6817 if (idx + 1 < methodt->rows)
6818 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6820 lastp = paramt->rows + 1;
6822 for (i = param_index; i < lastp; ++i) {
6825 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6826 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6828 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6831 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6836 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6837 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6838 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6845 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6850 MonoType *basetype = type;
6855 klass = mono_class_from_mono_type (type);
6856 if (klass->valuetype) {
6857 object = mono_object_new (domain, klass);
6858 retval = ((gchar *) object + sizeof (MonoObject));
6859 if (klass->enumtype)
6860 basetype = mono_class_enum_basetype (klass);
6865 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6872 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6876 memset (assembly, 0, sizeof (MonoAssemblyName));
6878 assembly->culture = "";
6879 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6881 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6884 while (g_ascii_isspace (*p) || *p == ',') {
6893 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6895 assembly->major = strtoul (p, &s, 10);
6896 if (s == p || *s != '.')
6899 assembly->minor = strtoul (p, &s, 10);
6900 if (s == p || *s != '.')
6903 assembly->build = strtoul (p, &s, 10);
6904 if (s == p || *s != '.')
6907 assembly->revision = strtoul (p, &s, 10);
6911 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6913 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6914 assembly->culture = "";
6917 assembly->culture = p;
6918 while (*p && *p != ',') {
6922 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6924 if (strncmp (p, "null", 4) == 0) {
6929 while (*p && *p != ',') {
6932 len = (p - start + 1);
6933 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6934 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6935 g_strlcpy ((char*)assembly->public_key_token, start, len);
6938 while (*p && *p != ',')
6942 while (g_ascii_isspace (*p) || *p == ',') {
6956 * mono_reflection_parse_type:
6959 * Parse a type name as accepted by the GetType () method and output the info
6960 * extracted in the info structure.
6961 * the name param will be mangled, so, make a copy before passing it to this function.
6962 * The fields in info will be valid until the memory pointed to by name is valid.
6964 * See also mono_type_get_name () below.
6966 * Returns: 0 on parse error.
6969 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6970 MonoTypeNameParse *info)
6972 char *start, *p, *w, *temp, *last_point, *startn;
6973 int in_modifiers = 0;
6974 int isbyref = 0, rank, arity = 0, i;
6976 start = p = w = name;
6978 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6979 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6980 info->name = info->name_space = NULL;
6981 info->nested = NULL;
6982 info->modifiers = NULL;
6983 info->type_arguments = NULL;
6985 /* last_point separates the namespace from the name */
6988 while (*p == ' ') p++, start++, w++, name++;
6993 *p = 0; /* NULL terminate the name */
6995 info->nested = g_list_append (info->nested, startn);
6996 /* we have parsed the nesting namespace + name */
7000 info->name_space = start;
7002 info->name = last_point + 1;
7004 info->name_space = (char *)"";
7023 i = strtol (p, &temp, 10);
7040 info->name_space = start;
7042 info->name = last_point + 1;
7044 info->name_space = (char *)"";
7051 if (isbyref) /* only one level allowed by the spec */
7054 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7058 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7064 info->type_arguments = g_ptr_array_new ();
7065 for (i = 0; i < arity; i++) {
7066 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7067 gboolean fqname = FALSE;
7069 g_ptr_array_add (info->type_arguments, subinfo);
7076 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7087 while (*p && (*p != ']'))
7095 if (g_ascii_isspace (*aname)) {
7102 !assembly_name_to_aname (&subinfo->assembly, aname))
7106 if (i + 1 < arity) {
7126 else if (*p == '*') /* '*' means unknown lower bound */
7127 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7134 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7145 if (g_ascii_isspace (*p)) {
7152 return 0; /* missing assembly name */
7153 if (!assembly_name_to_aname (&info->assembly, p))
7159 if (info->assembly.name)
7162 // *w = 0; /* terminate class name */
7164 if (!info->name || !*info->name)
7168 /* add other consistency checks */
7173 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7175 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7179 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7181 gboolean type_resolve = FALSE;
7183 MonoImage *rootimage = image;
7185 if (info->assembly.name) {
7186 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7187 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7189 * This could happen in the AOT compiler case when the search hook is not
7192 assembly = image->assembly;
7194 /* then we must load the assembly ourselve - see #60439 */
7195 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7199 image = assembly->image;
7200 } else if (!image) {
7201 image = mono_defaults.corlib;
7204 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7205 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7206 image = mono_defaults.corlib;
7207 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7214 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7219 gboolean bounded = FALSE;
7222 image = mono_defaults.corlib;
7225 klass = mono_class_from_name_case (image, info->name_space, info->name);
7227 klass = mono_class_from_name (image, info->name_space, info->name);
7230 for (mod = info->nested; mod; mod = mod->next) {
7231 gpointer iter = NULL;
7235 mono_class_init (parent);
7237 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7239 if (g_strcasecmp (klass->name, mod->data) == 0)
7242 if (strcmp (klass->name, mod->data) == 0)
7251 mono_class_init (klass);
7253 if (info->type_arguments) {
7254 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7255 MonoReflectionType *the_type;
7259 for (i = 0; i < info->type_arguments->len; i++) {
7260 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7262 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7263 if (!type_args [i]) {
7269 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7271 instance = mono_reflection_bind_generic_parameters (
7272 the_type, info->type_arguments->len, type_args);
7278 klass = mono_class_from_mono_type (instance);
7281 for (mod = info->modifiers; mod; mod = mod->next) {
7282 modval = GPOINTER_TO_UINT (mod->data);
7283 if (!modval) { /* byref: must be last modifier */
7284 return &klass->this_arg;
7285 } else if (modval == -1) {
7286 klass = mono_ptr_class_get (&klass->byval_arg);
7287 } else if (modval == -2) {
7289 } else { /* array rank */
7290 klass = mono_bounded_array_class_get (klass, modval, bounded);
7292 mono_class_init (klass);
7295 return &klass->byval_arg;
7299 * mono_reflection_get_type:
7300 * @image: a metadata context
7301 * @info: type description structure
7302 * @ignorecase: flag for case-insensitive string compares
7303 * @type_resolve: whenever type resolve was already tried
7305 * Build a MonoType from the type description in @info.
7310 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7311 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7315 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7317 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7321 g_assert (assembly->dynamic);
7323 /* Enumerate all modules */
7326 if (abuilder->modules) {
7327 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7328 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7329 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7335 if (!type && abuilder->loaded_modules) {
7336 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7337 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7338 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7348 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7351 MonoReflectionAssembly *assembly;
7355 if (image && image->dynamic)
7356 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7358 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7361 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7368 *type_resolve = TRUE;
7371 /* Reconstruct the type name */
7372 fullName = g_string_new ("");
7373 if (info->name_space && (info->name_space [0] != '\0'))
7374 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7376 g_string_printf (fullName, "%s", info->name);
7377 for (mod = info->nested; mod; mod = mod->next)
7378 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7380 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7382 if (assembly->assembly->dynamic)
7383 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7385 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7388 g_string_free (fullName, TRUE);
7393 mono_reflection_free_type_info (MonoTypeNameParse *info)
7395 g_list_free (info->modifiers);
7396 g_list_free (info->nested);
7398 if (info->type_arguments) {
7401 for (i = 0; i < info->type_arguments->len; i++) {
7402 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7404 mono_reflection_free_type_info (subinfo);
7405 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7409 g_ptr_array_free (info->type_arguments, TRUE);
7414 * mono_reflection_type_from_name:
7416 * @image: a metadata context (can be NULL).
7418 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7419 * it defaults to get the type from @image or, if @image is NULL or loading
7420 * from it fails, uses corlib.
7424 mono_reflection_type_from_name (char *name, MonoImage *image)
7426 MonoType *type = NULL;
7427 MonoTypeNameParse info;
7430 /* Make a copy since parse_type modifies its argument */
7431 tmp = g_strdup (name);
7433 /*g_print ("requested type %s\n", str);*/
7434 if (mono_reflection_parse_type (tmp, &info)) {
7435 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7439 mono_reflection_free_type_info (&info);
7444 * mono_reflection_get_token:
7446 * Return the metadata token of OBJ which should be an object
7447 * representing a metadata element.
7450 mono_reflection_get_token (MonoObject *obj)
7455 klass = obj->vtable->klass;
7457 if (strcmp (klass->name, "MethodBuilder") == 0) {
7458 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7460 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7461 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7462 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7464 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7465 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7466 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7468 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7469 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7470 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7471 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7472 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7473 } else if (strcmp (klass->name, "MonoType") == 0) {
7474 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7475 token = mono_class_from_mono_type (type)->type_token;
7476 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7477 strcmp (klass->name, "MonoMethod") == 0 ||
7478 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7479 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7480 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7481 if (m->method->is_inflated) {
7482 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7483 return inflated->declaring->token;
7485 token = m->method->token;
7487 } else if (strcmp (klass->name, "MonoField") == 0) {
7488 MonoReflectionField *f = (MonoReflectionField*)obj;
7490 if (is_field_on_inst (f->field)) {
7491 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7492 int field_index = f->field - dgclass->fields;
7495 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7496 obj = dgclass->field_objects [field_index];
7497 return mono_reflection_get_token (obj);
7499 token = mono_class_get_field_token (f->field);
7500 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7501 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7503 token = mono_class_get_property_token (p->property);
7504 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7505 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7507 token = mono_class_get_event_token (p->event);
7508 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7509 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7511 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7512 } else if (strcmp (klass->name, "Module") == 0) {
7513 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7516 } else if (strcmp (klass->name, "Assembly") == 0) {
7517 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7519 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7520 MonoException *ex = mono_get_exception_not_implemented (msg);
7522 mono_raise_exception (ex);
7529 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7531 int slen, type = t->type;
7532 MonoClass *tklass = t->data.klass;
7538 case MONO_TYPE_BOOLEAN: {
7539 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7544 case MONO_TYPE_CHAR:
7546 case MONO_TYPE_I2: {
7547 guint16 *val = g_malloc (sizeof (guint16));
7552 #if SIZEOF_VOID_P == 4
7558 case MONO_TYPE_I4: {
7559 guint32 *val = g_malloc (sizeof (guint32));
7564 #if SIZEOF_VOID_P == 8
7565 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7569 case MONO_TYPE_I8: {
7570 guint64 *val = g_malloc (sizeof (guint64));
7575 case MONO_TYPE_R8: {
7576 double *val = g_malloc (sizeof (double));
7581 case MONO_TYPE_VALUETYPE:
7582 if (t->data.klass->enumtype) {
7583 type = mono_class_enum_basetype (t->data.klass)->type;
7586 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7589 case MONO_TYPE_STRING:
7590 if (*p == (char)0xFF) {
7594 slen = mono_metadata_decode_value (p, &p);
7596 return mono_string_new_len (mono_domain_get (), p, slen);
7597 case MONO_TYPE_CLASS: {
7600 if (*p == (char)0xFF) {
7605 slen = mono_metadata_decode_value (p, &p);
7606 n = g_memdup (p, slen + 1);
7608 t = mono_reflection_type_from_name (n, image);
7610 g_warning ("Cannot load type '%s'", n);
7614 return mono_type_get_object (mono_domain_get (), t);
7618 case MONO_TYPE_OBJECT: {
7621 MonoClass *subc = NULL;
7626 } else if (subt == 0x0E) {
7627 type = MONO_TYPE_STRING;
7629 } else if (subt == 0x1D) {
7630 MonoType simple_type = {{0}};
7635 /* See Partition II, Appendix B3 */
7636 etype = MONO_TYPE_OBJECT;
7637 type = MONO_TYPE_SZARRAY;
7638 simple_type.type = etype;
7639 tklass = mono_class_from_mono_type (&simple_type);
7641 } else if (subt == 0x55) {
7644 slen = mono_metadata_decode_value (p, &p);
7645 n = g_memdup (p, slen + 1);
7647 t = mono_reflection_type_from_name (n, image);
7649 g_error ("Cannot load type '%s'", n);
7652 subc = mono_class_from_mono_type (t);
7653 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7654 MonoType simple_type = {{0}};
7655 simple_type.type = subt;
7656 subc = mono_class_from_mono_type (&simple_type);
7658 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7660 val = load_cattr_value (image, &subc->byval_arg, p, end);
7661 obj = mono_object_new (mono_domain_get (), subc);
7662 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7666 case MONO_TYPE_SZARRAY: {
7668 guint32 i, alen, basetype;
7671 if (alen == 0xffffffff) {
7675 arr = mono_array_new (mono_domain_get(), tklass, alen);
7676 basetype = tklass->byval_arg.type;
7677 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7678 basetype = mono_class_enum_basetype (tklass)->type;
7683 case MONO_TYPE_BOOLEAN:
7684 for (i = 0; i < alen; i++) {
7685 MonoBoolean val = *p++;
7686 mono_array_set (arr, MonoBoolean, i, val);
7689 case MONO_TYPE_CHAR:
7692 for (i = 0; i < alen; i++) {
7693 guint16 val = read16 (p);
7694 mono_array_set (arr, guint16, i, val);
7701 for (i = 0; i < alen; i++) {
7702 guint32 val = read32 (p);
7703 mono_array_set (arr, guint32, i, val);
7708 for (i = 0; i < alen; i++) {
7711 mono_array_set (arr, double, i, val);
7717 for (i = 0; i < alen; i++) {
7718 guint64 val = read64 (p);
7719 mono_array_set (arr, guint64, i, val);
7723 case MONO_TYPE_CLASS:
7724 case MONO_TYPE_OBJECT:
7725 case MONO_TYPE_STRING:
7726 for (i = 0; i < alen; i++) {
7727 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7728 mono_array_setref (arr, i, item);
7732 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7738 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7744 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7746 static MonoClass *klass;
7747 static MonoMethod *ctor;
7749 void *params [2], *unboxed;
7752 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7754 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7756 params [0] = mono_type_get_object (mono_domain_get (), t);
7758 retval = mono_object_new (mono_domain_get (), klass);
7759 unboxed = mono_object_unbox (retval);
7760 mono_runtime_invoke (ctor, unboxed, params, NULL);
7766 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7768 static MonoClass *klass;
7769 static MonoMethod *ctor;
7771 void *unboxed, *params [2];
7774 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7776 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7779 params [1] = typedarg;
7780 retval = mono_object_new (mono_domain_get (), klass);
7781 unboxed = mono_object_unbox (retval);
7782 mono_runtime_invoke (ctor, unboxed, params, NULL);
7788 type_is_reference (MonoType *type)
7790 switch (type->type) {
7791 case MONO_TYPE_BOOLEAN:
7792 case MONO_TYPE_CHAR:
7805 case MONO_TYPE_VALUETYPE:
7813 free_param_data (MonoMethodSignature *sig, void **params) {
7815 for (i = 0; i < sig->param_count; ++i) {
7816 if (!type_is_reference (sig->params [i]))
7817 g_free (params [i]);
7822 * Find the field index in the metadata FieldDef table.
7825 find_field_index (MonoClass *klass, MonoClassField *field) {
7828 for (i = 0; i < klass->field.count; ++i) {
7829 if (field == &klass->fields [i])
7830 return klass->field.first + 1 + i;
7836 * Find the property index in the metadata Property table.
7839 find_property_index (MonoClass *klass, MonoProperty *property) {
7842 for (i = 0; i < klass->ext->property.count; ++i) {
7843 if (property == &klass->ext->properties [i])
7844 return klass->ext->property.first + 1 + i;
7850 * Find the event index in the metadata Event table.
7853 find_event_index (MonoClass *klass, MonoEvent *event) {
7856 for (i = 0; i < klass->ext->event.count; ++i) {
7857 if (event == &klass->ext->events [i])
7858 return klass->ext->event.first + 1 + i;
7864 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7866 const char *p = (const char*)data;
7868 guint32 i, j, num_named;
7870 void *params_buf [32];
7872 MonoMethodSignature *sig;
7874 mono_class_init (method->klass);
7877 attr = mono_object_new (mono_domain_get (), method->klass);
7878 mono_runtime_invoke (method, attr, NULL, NULL);
7882 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7885 /*g_print ("got attr %s\n", method->klass->name);*/
7887 sig = mono_method_signature (method);
7888 if (sig->param_count < 32)
7889 params = params_buf;
7891 /* Allocate using GC so it gets GC tracking */
7892 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7896 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7897 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7901 attr = mono_object_new (mono_domain_get (), method->klass);
7902 mono_runtime_invoke (method, attr, params, NULL);
7903 free_param_data (method->signature, params);
7904 num_named = read16 (named);
7906 for (j = 0; j < num_named; j++) {
7908 char *name, named_type, data_type;
7909 named_type = *named++;
7910 data_type = *named++; /* type of data */
7911 if (data_type == MONO_TYPE_SZARRAY)
7912 data_type = *named++;
7913 if (data_type == MONO_TYPE_ENUM) {
7916 type_len = mono_metadata_decode_blob_size (named, &named);
7917 type_name = g_malloc (type_len + 1);
7918 memcpy (type_name, named, type_len);
7919 type_name [type_len] = 0;
7921 /* FIXME: lookup the type and check type consistency */
7924 name_len = mono_metadata_decode_blob_size (named, &named);
7925 name = g_malloc (name_len + 1);
7926 memcpy (name, named, name_len);
7927 name [name_len] = 0;
7929 if (named_type == 0x53) {
7930 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7931 void *val = load_cattr_value (image, field->type, named, &named);
7932 mono_field_set_value (attr, field, val);
7933 if (!type_is_reference (field->type))
7935 } else if (named_type == 0x54) {
7938 MonoType *prop_type;
7940 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7941 /* can we have more that 1 arg in a custom attr named property? */
7942 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7943 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7944 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7945 mono_property_set_value (prop, attr, pparams, NULL);
7946 if (!type_is_reference (prop_type))
7947 g_free (pparams [0]);
7952 if (params != params_buf)
7953 mono_gc_free_fixed (params);
7959 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7961 MonoArray *typedargs, *namedargs;
7962 MonoClass *attrklass;
7963 static MonoMethod *ctor;
7966 const char *p = (const char*)data;
7968 guint32 i, j, num_named;
7971 mono_class_init (method->klass);
7974 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7976 domain = mono_domain_get ();
7978 /* This is for Attributes with no parameters */
7979 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7980 params [0] = mono_method_get_object (domain, method, NULL);
7981 params [1] = params [2] = NULL;
7982 mono_runtime_invoke (method, attr, params, NULL);
7986 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7989 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7993 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7994 MonoObject *obj, *typedarg;
7997 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7998 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7999 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8000 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8001 mono_array_setref (typedargs, i, typedarg);
8003 if (!type_is_reference (mono_method_signature (method)->params [i]))
8008 num_named = read16 (named);
8009 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8011 attrklass = method->klass;
8012 for (j = 0; j < num_named; j++) {
8014 char *name, named_type, data_type;
8015 named_type = *named++;
8016 data_type = *named++; /* type of data */
8017 if (data_type == MONO_TYPE_SZARRAY)
8018 data_type = *named++;
8019 if (data_type == MONO_TYPE_ENUM) {
8022 type_len = mono_metadata_decode_blob_size (named, &named);
8023 type_name = g_malloc (type_len + 1);
8024 memcpy (type_name, named, type_len);
8025 type_name [type_len] = 0;
8027 /* FIXME: lookup the type and check type consistency */
8030 name_len = mono_metadata_decode_blob_size (named, &named);
8031 name = g_malloc (name_len + 1);
8032 memcpy (name, named, name_len);
8033 name [name_len] = 0;
8035 if (named_type == 0x53) {
8036 MonoObject *obj, *typedarg, *namedarg;
8037 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8038 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
8040 minfo = mono_field_get_object (domain, NULL, field);
8041 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8042 typedarg = create_cattr_typed_arg (field->type, obj);
8043 namedarg = create_cattr_named_arg (minfo, typedarg);
8044 mono_array_setref (namedargs, j, namedarg);
8045 if (!type_is_reference (field->type))
8047 } else if (named_type == 0x54) {
8048 MonoObject *obj, *typedarg, *namedarg;
8049 MonoType *prop_type;
8051 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8053 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8054 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8055 minfo = mono_property_get_object (domain, NULL, prop);
8056 val = load_cattr_value (image, prop_type, named, &named);
8057 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8058 typedarg = create_cattr_typed_arg (prop_type, obj);
8059 namedarg = create_cattr_named_arg (minfo, typedarg);
8060 mono_array_setref (namedargs, j, namedarg);
8061 if (!type_is_reference (prop_type))
8066 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8067 params [0] = mono_method_get_object (domain, method, NULL);
8068 params [1] = typedargs;
8069 params [2] = namedargs;
8070 mono_runtime_invoke (ctor, attr, params, NULL);
8075 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8081 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8082 for (i = 0; i < cinfo->num_attrs; ++i) {
8083 if (!cinfo->attrs [i].ctor)
8084 /* The cattr type is not finished yet */
8085 /* We should include the type name but cinfo doesn't contain it */
8086 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8087 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8088 mono_array_setref (result, i, attr);
8094 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8101 for (i = 0; i < cinfo->num_attrs; ++i) {
8102 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8106 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8108 for (i = 0; i < cinfo->num_attrs; ++i) {
8109 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8110 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8111 mono_array_setref (result, n, attr);
8119 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8125 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8126 for (i = 0; i < cinfo->num_attrs; ++i) {
8127 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8128 mono_array_setref (result, i, attr);
8134 * mono_custom_attrs_from_index:
8136 * Returns: NULL if no attributes are found or if a loading error occurs.
8139 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8141 guint32 mtoken, i, len;
8142 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8144 MonoCustomAttrInfo *ainfo;
8145 GList *tmp, *list = NULL;
8148 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8150 i = mono_metadata_custom_attrs_from_index (image, idx);
8154 while (i < ca->rows) {
8155 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8157 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8160 len = g_list_length (list);
8163 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8164 ainfo->num_attrs = len;
8165 ainfo->image = image;
8166 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8167 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8168 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8169 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8170 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8171 mtoken |= MONO_TOKEN_METHOD_DEF;
8173 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8174 mtoken |= MONO_TOKEN_MEMBER_REF;
8177 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8180 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8181 if (!ainfo->attrs [i].ctor) {
8182 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8187 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8188 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8189 ainfo->attrs [i].data = (guchar*)data;
8197 mono_custom_attrs_from_method (MonoMethod *method)
8202 * An instantiated method has the same cattrs as the generic method definition.
8204 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8205 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8207 if (method->is_inflated)
8208 method = ((MonoMethodInflated *) method)->declaring;
8210 if (method->dynamic || method->klass->image->dynamic)
8211 return lookup_custom_attr (method->klass->image, method);
8214 /* Synthetic methods */
8217 idx = mono_method_get_index (method);
8218 idx <<= MONO_CUSTOM_ATTR_BITS;
8219 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8220 return mono_custom_attrs_from_index (method->klass->image, idx);
8224 mono_custom_attrs_from_class (MonoClass *klass)
8228 if (klass->generic_class)
8229 klass = klass->generic_class->container_class;
8231 if (klass->image->dynamic)
8232 return lookup_custom_attr (klass->image, klass);
8234 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8235 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8236 idx <<= MONO_CUSTOM_ATTR_BITS;
8237 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8239 idx = mono_metadata_token_index (klass->type_token);
8240 idx <<= MONO_CUSTOM_ATTR_BITS;
8241 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8243 return mono_custom_attrs_from_index (klass->image, idx);
8247 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8251 if (assembly->image->dynamic)
8252 return lookup_custom_attr (assembly->image, assembly);
8253 idx = 1; /* there is only one assembly */
8254 idx <<= MONO_CUSTOM_ATTR_BITS;
8255 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8256 return mono_custom_attrs_from_index (assembly->image, idx);
8259 static MonoCustomAttrInfo*
8260 mono_custom_attrs_from_module (MonoImage *image)
8265 return lookup_custom_attr (image, image);
8266 idx = 1; /* there is only one module */
8267 idx <<= MONO_CUSTOM_ATTR_BITS;
8268 idx |= MONO_CUSTOM_ATTR_MODULE;
8269 return mono_custom_attrs_from_index (image, idx);
8273 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8277 if (klass->image->dynamic) {
8278 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8279 return lookup_custom_attr (klass->image, property);
8281 idx = find_property_index (klass, property);
8282 idx <<= MONO_CUSTOM_ATTR_BITS;
8283 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8284 return mono_custom_attrs_from_index (klass->image, idx);
8288 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8292 if (klass->image->dynamic) {
8293 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8294 return lookup_custom_attr (klass->image, event);
8296 idx = find_event_index (klass, event);
8297 idx <<= MONO_CUSTOM_ATTR_BITS;
8298 idx |= MONO_CUSTOM_ATTR_EVENT;
8299 return mono_custom_attrs_from_index (klass->image, idx);
8303 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8306 if (klass->image->dynamic) {
8307 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8308 return lookup_custom_attr (klass->image, field);
8310 idx = find_field_index (klass, field);
8311 idx <<= MONO_CUSTOM_ATTR_BITS;
8312 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8313 return mono_custom_attrs_from_index (klass->image, idx);
8317 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8320 guint32 i, idx, method_index;
8321 guint32 param_list, param_last, param_pos, found;
8323 MonoReflectionMethodAux *aux;
8326 * An instantiated method has the same cattrs as the generic method definition.
8328 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8329 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8331 if (method->is_inflated)
8332 method = ((MonoMethodInflated *) method)->declaring;
8334 if (method->klass->image->dynamic) {
8335 MonoCustomAttrInfo *res, *ainfo;
8338 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8339 if (!aux || !aux->param_cattr)
8342 /* Need to copy since it will be freed later */
8343 ainfo = aux->param_cattr [param];
8344 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8345 res = g_malloc0 (size);
8346 memcpy (res, ainfo, size);
8350 image = method->klass->image;
8351 method_index = mono_method_get_index (method);
8352 ca = &image->tables [MONO_TABLE_METHOD];
8354 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8355 if (method_index == ca->rows) {
8356 ca = &image->tables [MONO_TABLE_PARAM];
8357 param_last = ca->rows + 1;
8359 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8360 ca = &image->tables [MONO_TABLE_PARAM];
8363 for (i = param_list; i < param_last; ++i) {
8364 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8365 if (param_pos == param) {
8373 idx <<= MONO_CUSTOM_ATTR_BITS;
8374 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8375 return mono_custom_attrs_from_index (image, idx);
8379 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8383 for (i = 0; i < ainfo->num_attrs; ++i) {
8384 klass = ainfo->attrs [i].ctor->klass;
8385 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8392 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8399 for (i = 0; i < ainfo->num_attrs; ++i) {
8400 klass = ainfo->attrs [i].ctor->klass;
8401 if (mono_class_has_parent (klass, attr_klass)) {
8406 if (attr_index == -1)
8409 attrs = mono_custom_attrs_construct (ainfo);
8411 return mono_array_get (attrs, MonoObject*, attr_index);
8417 * mono_reflection_get_custom_attrs_info:
8418 * @obj: a reflection object handle
8420 * Return the custom attribute info for attributes defined for the
8421 * reflection handle @obj. The objects.
8423 * FIXME this function leaks like a sieve for SRE objects.
8426 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8429 MonoCustomAttrInfo *cinfo = NULL;
8431 klass = obj->vtable->klass;
8432 if (klass == mono_defaults.monotype_class) {
8433 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8434 klass = mono_class_from_mono_type (type);
8435 cinfo = mono_custom_attrs_from_class (klass);
8436 } else if (strcmp ("Assembly", klass->name) == 0) {
8437 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8438 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8439 } else if (strcmp ("Module", klass->name) == 0) {
8440 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8441 cinfo = mono_custom_attrs_from_module (module->image);
8442 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8443 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8444 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8445 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8446 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8447 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8448 } else if (strcmp ("MonoField", klass->name) == 0) {
8449 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8450 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8451 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8452 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8453 cinfo = mono_custom_attrs_from_method (rmethod->method);
8454 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8455 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8456 cinfo = mono_custom_attrs_from_method (rmethod->method);
8457 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8458 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8459 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8460 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8461 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8462 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8463 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8464 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8465 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8466 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8467 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8468 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8469 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8470 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8471 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8472 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8473 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8474 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8475 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8476 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8477 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8478 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8479 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8480 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8481 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8482 } else { /* handle other types here... */
8483 g_error ("get custom attrs not yet supported for %s", klass->name);
8490 * mono_reflection_get_custom_attrs_by_type:
8491 * @obj: a reflection object handle
8493 * Return an array with all the custom attributes defined of the
8494 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8495 * of that type are returned. The objects are fully build. Return NULL if a loading error
8499 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8502 MonoCustomAttrInfo *cinfo;
8504 cinfo = mono_reflection_get_custom_attrs_info (obj);
8507 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8509 result = mono_custom_attrs_construct (cinfo);
8511 mono_custom_attrs_free (cinfo);
8513 if (mono_loader_get_last_error ())
8515 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8522 * mono_reflection_get_custom_attrs:
8523 * @obj: a reflection object handle
8525 * Return an array with all the custom attributes defined of the
8526 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8530 mono_reflection_get_custom_attrs (MonoObject *obj)
8532 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8536 * mono_reflection_get_custom_attrs_data:
8537 * @obj: a reflection obj handle
8539 * Returns an array of System.Reflection.CustomAttributeData,
8540 * which include information about attributes reflected on
8541 * types loaded using the Reflection Only methods
8544 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8547 MonoCustomAttrInfo *cinfo;
8549 cinfo = mono_reflection_get_custom_attrs_info (obj);
8551 result = mono_custom_attrs_data_construct (cinfo);
8553 mono_custom_attrs_free (cinfo);
8555 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8560 static MonoReflectionType*
8561 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8563 MonoMethod *method_get_underlying_system_type;
8565 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8566 mono_class_get_method_from_name (mono_object_class (t),
8567 "get_UnderlyingSystemType",
8569 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8572 #ifndef DISABLE_REFLECTION_EMIT
8575 is_corlib_type (MonoClass *class)
8577 return class->image == mono_defaults.corlib;
8581 is_usertype (MonoReflectionType *ref)
8583 MonoClass *class = mono_object_class (ref);
8584 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8587 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8588 static MonoClass *cached_class; \
8590 return cached_class == _class; \
8591 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8592 cached_class = _class; \
8599 is_sre_array (MonoClass *class)
8601 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8605 is_sre_byref (MonoClass *class)
8607 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8611 is_sre_pointer (MonoClass *class)
8613 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8617 is_sre_generic_instance (MonoClass *class)
8619 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8623 mono_reflection_type_get_handle (MonoReflectionType* ref)
8631 if (is_usertype (ref)) {
8632 ref = mono_reflection_type_get_underlying_system_type (ref);
8633 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8638 class = mono_object_class (ref);
8640 if (is_sre_array (class)) {
8642 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8643 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8645 if (sre_array->rank == 0) //single dimentional array
8646 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8648 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8649 sre_array->type.type = res;
8651 } else if (is_sre_byref (class)) {
8653 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8654 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8656 res = &mono_class_from_mono_type (base)->this_arg;
8657 sre_byref->type.type = res;
8659 } else if (is_sre_pointer (class)) {
8661 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8662 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8664 res = &mono_ptr_class_get (base)->byval_arg;
8665 sre_pointer->type.type = res;
8667 } else if (is_sre_generic_instance (class)) {
8668 MonoType *res, **types;
8669 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8672 count = mono_array_length (gclass->type_arguments);
8673 types = g_new0 (MonoType*, count);
8674 for (i = 0; i < count; ++i) {
8675 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8676 types [i] = mono_reflection_type_get_handle (t);
8679 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8682 gclass->type.type = res;
8686 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8690 static MonoReflectionType*
8691 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8693 if (!type || type->type)
8696 if (is_usertype (type)) {
8697 type = mono_reflection_type_get_underlying_system_type (type);
8698 if (is_usertype (type))
8699 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8706 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8708 mono_reflection_type_get_handle (type);
8712 * LOCKING: Assumes the loader lock is held.
8714 static MonoMethodSignature*
8715 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8716 MonoMethodSignature *sig;
8719 count = parameters? mono_array_length (parameters): 0;
8721 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8722 sig->param_count = count;
8723 sig->sentinelpos = -1; /* FIXME */
8724 for (i = 0; i < count; ++i)
8725 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8730 * LOCKING: Assumes the loader lock is held.
8732 static MonoMethodSignature*
8733 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8734 MonoMethodSignature *sig;
8736 sig = parameters_to_signature (image, ctor->parameters);
8737 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8738 sig->ret = &mono_defaults.void_class->byval_arg;
8743 * LOCKING: Assumes the loader lock is held.
8745 static MonoMethodSignature*
8746 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8747 MonoMethodSignature *sig;
8749 sig = parameters_to_signature (image, method->parameters);
8750 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8751 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8752 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8756 static MonoMethodSignature*
8757 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8758 MonoMethodSignature *sig;
8760 sig = parameters_to_signature (NULL, method->parameters);
8761 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8762 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8763 sig->generic_param_count = 0;
8768 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8770 MonoClass *klass = mono_object_class (prop);
8771 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8772 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8773 *name = mono_string_to_utf8 (pb->name);
8774 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8776 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8777 *name = g_strdup (p->property->name);
8778 if (p->property->get)
8779 *type = mono_method_signature (p->property->get)->ret;
8781 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8786 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8788 MonoClass *klass = mono_object_class (field);
8789 if (strcmp (klass->name, "FieldBuilder") == 0) {
8790 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8791 *name = mono_string_to_utf8 (fb->name);
8792 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8794 MonoReflectionField *f = (MonoReflectionField *)field;
8795 *name = g_strdup (mono_field_get_name (f->field));
8796 *type = f->field->type;
8799 #endif /* !DISABLE_REFLECTION_EMIT */
8802 * Encode a value in a custom attribute stream of bytes.
8803 * The value to encode is either supplied as an object in argument val
8804 * (valuetypes are boxed), or as a pointer to the data in the
8806 * @type represents the type of the value
8807 * @buffer is the start of the buffer
8808 * @p the current position in the buffer
8809 * @buflen contains the size of the buffer and is used to return the new buffer size
8810 * if this needs to be realloced.
8811 * @retbuffer and @retp return the start and the position of the buffer
8814 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8816 MonoTypeEnum simple_type;
8818 if ((p-buffer) + 10 >= *buflen) {
8821 newbuf = g_realloc (buffer, *buflen);
8822 p = newbuf + (p-buffer);
8826 argval = ((char*)arg + sizeof (MonoObject));
8827 simple_type = type->type;
8829 switch (simple_type) {
8830 case MONO_TYPE_BOOLEAN:
8835 case MONO_TYPE_CHAR:
8838 swap_with_size (p, argval, 2, 1);
8844 swap_with_size (p, argval, 4, 1);
8848 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8858 swap_with_size (p, argval, 8, 1);
8864 swap_with_size (p, argval, 8, 1);
8867 case MONO_TYPE_VALUETYPE:
8868 if (type->data.klass->enumtype) {
8869 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8872 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8875 case MONO_TYPE_STRING: {
8882 str = mono_string_to_utf8 ((MonoString*)arg);
8883 slen = strlen (str);
8884 if ((p-buffer) + 10 + slen >= *buflen) {
8888 newbuf = g_realloc (buffer, *buflen);
8889 p = newbuf + (p-buffer);
8892 mono_metadata_encode_value (slen, p, &p);
8893 memcpy (p, str, slen);
8898 case MONO_TYPE_CLASS: {
8907 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8908 slen = strlen (str);
8909 if ((p-buffer) + 10 + slen >= *buflen) {
8913 newbuf = g_realloc (buffer, *buflen);
8914 p = newbuf + (p-buffer);
8917 mono_metadata_encode_value (slen, p, &p);
8918 memcpy (p, str, slen);
8923 case MONO_TYPE_SZARRAY: {
8925 MonoClass *eclass, *arg_eclass;
8928 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8931 len = mono_array_length ((MonoArray*)arg);
8933 *p++ = (len >> 8) & 0xff;
8934 *p++ = (len >> 16) & 0xff;
8935 *p++ = (len >> 24) & 0xff;
8937 *retbuffer = buffer;
8938 eclass = type->data.klass;
8939 arg_eclass = mono_object_class (arg)->element_class;
8942 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8943 eclass = mono_defaults.object_class;
8945 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8946 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8947 int elsize = mono_class_array_element_size (arg_eclass);
8948 for (i = 0; i < len; ++i) {
8949 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8952 } else if (eclass->valuetype && arg_eclass->valuetype) {
8953 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8954 int elsize = mono_class_array_element_size (eclass);
8955 for (i = 0; i < len; ++i) {
8956 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8960 for (i = 0; i < len; ++i) {
8961 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8966 case MONO_TYPE_OBJECT: {
8972 * The parameter type is 'object' but the type of the actual
8973 * argument is not. So we have to add type information to the blob
8974 * too. This is completely undocumented in the spec.
8978 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8983 klass = mono_object_class (arg);
8985 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8988 } else if (klass->enumtype) {
8990 } else if (klass == mono_defaults.string_class) {
8991 simple_type = MONO_TYPE_STRING;
8994 } else if (klass->rank == 1) {
8996 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8997 /* See Partition II, Appendix B3 */
9000 *p++ = klass->element_class->byval_arg.type;
9001 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9003 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9004 *p++ = simple_type = klass->byval_arg.type;
9007 g_error ("unhandled type in custom attr");
9009 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9010 slen = strlen (str);
9011 if ((p-buffer) + 10 + slen >= *buflen) {
9015 newbuf = g_realloc (buffer, *buflen);
9016 p = newbuf + (p-buffer);
9019 mono_metadata_encode_value (slen, p, &p);
9020 memcpy (p, str, slen);
9023 simple_type = mono_class_enum_basetype (klass)->type;
9027 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9030 *retbuffer = buffer;
9034 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9036 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9037 char *str = type_get_qualified_name (type, NULL);
9038 int slen = strlen (str);
9042 * This seems to be optional...
9045 mono_metadata_encode_value (slen, p, &p);
9046 memcpy (p, str, slen);
9049 } else if (type->type == MONO_TYPE_OBJECT) {
9051 } else if (type->type == MONO_TYPE_CLASS) {
9052 /* it should be a type: encode_cattr_value () has the check */
9055 mono_metadata_encode_value (type->type, p, &p);
9056 if (type->type == MONO_TYPE_SZARRAY)
9057 /* See the examples in Partition VI, Annex B */
9058 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9064 #ifndef DISABLE_REFLECTION_EMIT
9066 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9069 /* Preallocate a large enough buffer */
9070 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9071 char *str = type_get_qualified_name (type, NULL);
9074 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9075 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9081 len += strlen (name);
9083 if ((p-buffer) + 20 + len >= *buflen) {
9087 newbuf = g_realloc (buffer, *buflen);
9088 p = newbuf + (p-buffer);
9092 encode_field_or_prop_type (type, p, &p);
9094 len = strlen (name);
9095 mono_metadata_encode_value (len, p, &p);
9096 memcpy (p, name, len);
9098 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9100 *retbuffer = buffer;
9104 * mono_reflection_get_custom_attrs_blob:
9105 * @ctor: custom attribute constructor
9106 * @ctorArgs: arguments o the constructor
9112 * Creates the blob of data that needs to be saved in the metadata and that represents
9113 * the custom attributed described by @ctor, @ctorArgs etc.
9114 * Returns: a Byte array representing the blob of data.
9117 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9120 MonoMethodSignature *sig;
9125 MONO_ARCH_SAVE_REGS;
9127 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9128 /* sig is freed later so allocate it in the heap */
9129 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9131 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9134 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9136 p = buffer = g_malloc (buflen);
9137 /* write the prolog */
9140 for (i = 0; i < sig->param_count; ++i) {
9141 arg = mono_array_get (ctorArgs, MonoObject*, i);
9142 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9146 i += mono_array_length (properties);
9148 i += mono_array_length (fields);
9150 *p++ = (i >> 8) & 0xff;
9153 for (i = 0; i < mono_array_length (properties); ++i) {
9157 prop = mono_array_get (properties, gpointer, i);
9158 get_prop_name_and_type (prop, &pname, &ptype);
9159 *p++ = 0x54; /* PROPERTY signature */
9160 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9167 for (i = 0; i < mono_array_length (fields); ++i) {
9171 field = mono_array_get (fields, gpointer, i);
9172 get_field_name_and_type (field, &fname, &ftype);
9173 *p++ = 0x53; /* FIELD signature */
9174 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9179 g_assert (p - buffer <= buflen);
9180 buflen = p - buffer;
9181 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9182 p = mono_array_addr (result, char, 0);
9183 memcpy (p, buffer, buflen);
9185 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9191 * mono_reflection_setup_internal_class:
9192 * @tb: a TypeBuilder object
9194 * Creates a MonoClass that represents the TypeBuilder.
9195 * This is a trick that lets us simplify a lot of reflection code
9196 * (and will allow us to support Build and Run assemblies easier).
9199 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9201 MonoClass *klass, *parent;
9203 MONO_ARCH_SAVE_REGS;
9205 RESOLVE_TYPE (tb->parent);
9207 mono_loader_lock ();
9210 /* check so we can compile corlib correctly */
9211 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9212 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9213 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9215 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9221 /* the type has already being created: it means we just have to change the parent */
9222 if (tb->type.type) {
9223 klass = mono_class_from_mono_type (tb->type.type);
9224 klass->parent = NULL;
9225 /* fool mono_class_setup_parent */
9226 klass->supertypes = NULL;
9227 mono_class_setup_parent (klass, parent);
9228 mono_class_setup_mono_type (klass);
9229 mono_loader_unlock ();
9233 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9235 klass->image = &tb->module->dynamic_image->image;
9237 klass->inited = 1; /* we lie to the runtime */
9238 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9239 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9240 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9241 klass->flags = tb->attrs;
9243 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9245 klass->element_class = klass;
9247 MOVING_GC_REGISTER (&klass->reflection_info);
9248 klass->reflection_info = tb;
9250 /* Put into cache so mono_class_get () will find it */
9251 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9253 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9254 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9256 if (parent != NULL) {
9257 mono_class_setup_parent (klass, parent);
9258 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9259 const char *old_n = klass->name;
9260 /* trick to get relative numbering right when compiling corlib */
9261 klass->name = "BuildingObject";
9262 mono_class_setup_parent (klass, mono_defaults.object_class);
9263 klass->name = old_n;
9266 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9267 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9268 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9269 klass->instance_size = sizeof (MonoObject);
9270 klass->size_inited = 1;
9271 mono_class_setup_vtable_general (klass, NULL, 0);
9274 mono_class_setup_mono_type (klass);
9276 mono_class_setup_supertypes (klass);
9279 * FIXME: handle interfaces.
9282 tb->type.type = &klass->byval_arg;
9284 if (tb->nesting_type) {
9285 g_assert (tb->nesting_type->type);
9286 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9289 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9291 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9293 mono_loader_unlock ();
9297 * mono_reflection_setup_generic_class:
9298 * @tb: a TypeBuilder object
9300 * Setup the generic class before adding the first generic parameter.
9303 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9308 * mono_reflection_create_generic_class:
9309 * @tb: a TypeBuilder object
9311 * Creates the generic class after all generic parameters have been added.
9314 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9319 MONO_ARCH_SAVE_REGS;
9321 klass = mono_class_from_mono_type (tb->type.type);
9323 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9325 if (klass->generic_container || (count == 0))
9328 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9330 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9332 klass->generic_container->owner.klass = klass;
9333 klass->generic_container->type_argc = count;
9334 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9336 klass->is_generic = 1;
9338 for (i = 0; i < count; i++) {
9339 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9340 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9341 klass->generic_container->type_params [i] = *param;
9342 /*Make sure we are a diferent type instance */
9343 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9344 klass->generic_container->type_params [i].info.pklass = NULL;
9346 g_assert (klass->generic_container->type_params [i].param.owner);
9349 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9353 * mono_reflection_create_internal_class:
9354 * @tb: a TypeBuilder object
9356 * Actually create the MonoClass that is associated with the TypeBuilder.
9359 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9363 MONO_ARCH_SAVE_REGS;
9365 klass = mono_class_from_mono_type (tb->type.type);
9367 mono_loader_lock ();
9368 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9369 MonoReflectionFieldBuilder *fb;
9371 MonoType *enum_basetype;
9373 g_assert (tb->fields != NULL);
9374 g_assert (mono_array_length (tb->fields) >= 1);
9376 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9378 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9379 mono_loader_unlock ();
9383 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9384 klass->element_class = mono_class_from_mono_type (enum_basetype);
9385 if (!klass->element_class)
9386 klass->element_class = mono_class_from_mono_type (enum_basetype);
9389 * get the element_class from the current corlib.
9391 ec = default_class_from_mono_type (enum_basetype);
9392 klass->instance_size = ec->instance_size;
9393 klass->size_inited = 1;
9395 * this is almost safe to do with enums and it's needed to be able
9396 * to create objects of the enum type (for use in SetConstant).
9398 /* FIXME: Does this mean enums can't have method overrides ? */
9399 mono_class_setup_vtable_general (klass, NULL, 0);
9401 mono_loader_unlock ();
9404 static MonoMarshalSpec*
9405 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9406 MonoReflectionMarshal *minfo)
9408 MonoMarshalSpec *res;
9410 res = image_g_new0 (image, MonoMarshalSpec, 1);
9411 res->native = minfo->type;
9413 switch (minfo->type) {
9414 case MONO_NATIVE_LPARRAY:
9415 res->data.array_data.elem_type = minfo->eltype;
9416 if (minfo->has_size) {
9417 res->data.array_data.param_num = minfo->param_num;
9418 res->data.array_data.num_elem = minfo->count;
9419 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9422 res->data.array_data.param_num = -1;
9423 res->data.array_data.num_elem = -1;
9424 res->data.array_data.elem_mult = -1;
9428 case MONO_NATIVE_BYVALTSTR:
9429 case MONO_NATIVE_BYVALARRAY:
9430 res->data.array_data.num_elem = minfo->count;
9433 case MONO_NATIVE_CUSTOM:
9434 if (minfo->marshaltyperef)
9435 res->data.custom_data.custom_name =
9436 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9438 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9447 #endif /* !DISABLE_REFLECTION_EMIT */
9449 MonoReflectionMarshal*
9450 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9451 MonoMarshalSpec *spec)
9453 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9454 MonoReflectionMarshal *minfo;
9457 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9458 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9459 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9460 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9463 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9464 minfo->type = spec->native;
9466 switch (minfo->type) {
9467 case MONO_NATIVE_LPARRAY:
9468 minfo->eltype = spec->data.array_data.elem_type;
9469 minfo->count = spec->data.array_data.num_elem;
9470 minfo->param_num = spec->data.array_data.param_num;
9473 case MONO_NATIVE_BYVALTSTR:
9474 case MONO_NATIVE_BYVALARRAY:
9475 minfo->count = spec->data.array_data.num_elem;
9478 case MONO_NATIVE_CUSTOM:
9479 if (spec->data.custom_data.custom_name) {
9480 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9482 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9484 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9486 if (spec->data.custom_data.cookie)
9487 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9497 #ifndef DISABLE_REFLECTION_EMIT
9499 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9500 ReflectionMethodBuilder *rmb,
9501 MonoMethodSignature *sig)
9504 MonoMethodNormal *pm;
9505 MonoMarshalSpec **specs;
9506 MonoReflectionMethodAux *method_aux;
9512 * Methods created using a MethodBuilder should have their memory allocated
9513 * inside the image mempool, while dynamic methods should have their memory
9516 dynamic = rmb->refs != NULL;
9517 image = dynamic ? NULL : klass->image;
9520 g_assert (!klass->generic_class);
9522 mono_loader_lock ();
9524 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9525 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9526 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9528 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9530 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9532 pm = (MonoMethodNormal*)m;
9534 m->dynamic = dynamic;
9536 m->flags = rmb->attrs;
9537 m->iflags = rmb->iattrs;
9538 m->name = mono_string_to_utf8_image (image, rmb->name);
9541 m->skip_visibility = rmb->skip_visibility;
9543 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9545 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9546 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9549 m->signature->pinvoke = 1;
9550 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9551 m->signature->pinvoke = 1;
9553 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9555 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9556 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9558 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9560 if (klass->image->dynamic)
9561 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9563 mono_loader_unlock ();
9566 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9567 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9568 MonoMethodHeader *header;
9570 gint32 max_stack, i;
9571 gint32 num_locals = 0;
9572 gint32 num_clauses = 0;
9576 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9577 code_size = rmb->ilgen->code_len;
9578 max_stack = rmb->ilgen->max_stack;
9579 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9580 if (rmb->ilgen->ex_handlers)
9581 num_clauses = method_count_clauses (rmb->ilgen);
9584 code = mono_array_addr (rmb->code, guint8, 0);
9585 code_size = mono_array_length (rmb->code);
9586 /* we probably need to run a verifier on the code... */
9596 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9597 header->code_size = code_size;
9598 header->code = image_g_malloc (image, code_size);
9599 memcpy ((char*)header->code, code, code_size);
9600 header->max_stack = max_stack;
9601 header->init_locals = rmb->init_locals;
9602 header->num_locals = num_locals;
9604 for (i = 0; i < num_locals; ++i) {
9605 MonoReflectionLocalBuilder *lb =
9606 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9608 header->locals [i] = image_g_new0 (image, MonoType, 1);
9609 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9612 header->num_clauses = num_clauses;
9614 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9615 rmb->ilgen, num_clauses);
9618 pm->header = header;
9621 if (rmb->generic_params) {
9622 int count = mono_array_length (rmb->generic_params);
9623 MonoGenericContainer *container;
9625 container = rmb->generic_container;
9627 m->is_generic = TRUE;
9628 mono_method_set_generic_container (m, container);
9630 container->type_argc = count;
9631 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9632 container->owner.method = m;
9634 for (i = 0; i < count; i++) {
9635 MonoReflectionGenericParam *gp =
9636 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9637 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9638 container->type_params [i] = *param;
9641 if (klass->generic_container) {
9642 container->parent = klass->generic_container;
9643 container->context.class_inst = klass->generic_container->context.class_inst;
9645 container->context.method_inst = mono_get_shared_generic_inst (container);
9649 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9653 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9655 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9656 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9657 for (i = 0; i < rmb->nrefs; ++i)
9658 data [i + 1] = rmb->refs [i];
9663 /* Parameter info */
9666 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9667 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9668 for (i = 0; i <= m->signature->param_count; ++i) {
9669 MonoReflectionParamBuilder *pb;
9670 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9671 if ((i > 0) && (pb->attrs)) {
9672 /* Make a copy since it might point to a shared type structure */
9673 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9674 m->signature->params [i - 1]->attrs = pb->attrs;
9677 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9678 MonoDynamicImage *assembly;
9679 guint32 idx, def_type, len;
9683 if (!method_aux->param_defaults) {
9684 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9685 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9687 assembly = (MonoDynamicImage*)klass->image;
9688 idx = encode_constant (assembly, pb->def_value, &def_type);
9689 /* Copy the data from the blob since it might get realloc-ed */
9690 p = assembly->blob.data + idx;
9691 len = mono_metadata_decode_blob_size (p, &p2);
9693 method_aux->param_defaults [i] = image_g_malloc (image, len);
9694 method_aux->param_default_types [i] = def_type;
9695 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9699 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9701 if (!method_aux->param_cattr)
9702 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9703 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9709 /* Parameter marshalling */
9712 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9713 MonoReflectionParamBuilder *pb;
9714 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9715 if (pb->marshal_info) {
9717 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9718 specs [pb->position] =
9719 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9723 if (specs != NULL) {
9725 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9726 method_aux->param_marshall = specs;
9729 if (klass->image->dynamic && method_aux)
9730 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9732 mono_loader_unlock ();
9738 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9740 ReflectionMethodBuilder rmb;
9741 MonoMethodSignature *sig;
9743 mono_loader_lock ();
9744 sig = ctor_builder_to_signature (klass->image, mb);
9745 mono_loader_unlock ();
9747 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9749 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9750 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9752 /* If we are in a generic class, we might be called multiple times from inflate_method */
9753 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9754 /* ilgen is no longer needed */
9762 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9764 ReflectionMethodBuilder rmb;
9765 MonoMethodSignature *sig;
9767 mono_loader_lock ();
9768 sig = method_builder_to_signature (klass->image, mb);
9769 mono_loader_unlock ();
9771 reflection_methodbuilder_from_method_builder (&rmb, mb);
9773 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9774 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9776 /* If we are in a generic class, we might be called multiple times from inflate_method */
9777 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9778 /* ilgen is no longer needed */
9784 static MonoClassField*
9785 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9787 MonoClassField *field;
9790 field = g_new0 (MonoClassField, 1);
9792 field->name = mono_string_to_utf8 (fb->name);
9793 if (fb->attrs || fb->modreq || fb->modopt) {
9794 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9795 field->type->attrs = fb->attrs;
9797 g_assert (klass->image->dynamic);
9798 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9799 g_free (field->type);
9800 field->type = custom;
9802 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9804 if (fb->offset != -1)
9805 field->offset = fb->offset;
9806 field->parent = klass;
9807 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9809 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9816 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9819 MonoReflectionTypeBuilder *tb = NULL;
9820 gboolean is_dynamic = FALSE;
9824 mono_loader_lock ();
9826 domain = mono_object_domain (type);
9828 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9829 tb = (MonoReflectionTypeBuilder *) type;
9832 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9833 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9835 tb = rgi->generic_type;
9839 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9840 if (tb && tb->generic_container)
9841 mono_reflection_create_generic_class (tb);
9843 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9844 if (!klass->generic_container) {
9845 mono_loader_unlock ();
9849 if (klass->wastypebuilder) {
9850 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9855 mono_loader_unlock ();
9857 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9859 return &geninst->byval_arg;
9863 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9865 MonoGenericClass *gclass;
9866 MonoGenericInst *inst;
9868 g_assert (klass->generic_container);
9870 inst = mono_metadata_get_generic_inst (type_argc, types);
9871 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9873 return mono_generic_class_get_class (gclass);
9876 MonoReflectionMethod*
9877 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9880 MonoMethod *method, *inflated;
9881 MonoMethodInflated *imethod;
9882 MonoGenericContext tmp_context;
9883 MonoGenericInst *ginst;
9884 MonoType **type_argv;
9887 MONO_ARCH_SAVE_REGS;
9889 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9890 #ifndef DISABLE_REFLECTION_EMIT
9891 MonoReflectionMethodBuilder *mb = NULL;
9892 MonoReflectionTypeBuilder *tb;
9895 mb = (MonoReflectionMethodBuilder *) rmethod;
9896 tb = (MonoReflectionTypeBuilder *) mb->type;
9897 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9899 method = methodbuilder_to_mono_method (klass, mb);
9901 g_assert_not_reached ();
9905 method = rmethod->method;
9908 klass = method->klass;
9910 if (method->is_inflated)
9911 method = ((MonoMethodInflated *) method)->declaring;
9913 count = mono_method_signature (method)->generic_param_count;
9914 if (count != mono_array_length (types))
9917 type_argv = g_new0 (MonoType *, count);
9918 for (i = 0; i < count; i++) {
9919 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9920 type_argv [i] = mono_reflection_type_get_handle (garg);
9922 ginst = mono_metadata_get_generic_inst (count, type_argv);
9925 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9926 tmp_context.method_inst = ginst;
9928 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9929 imethod = (MonoMethodInflated *) inflated;
9931 if (method->klass->image->dynamic) {
9932 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9934 * This table maps metadata structures representing inflated methods/fields
9935 * to the reflection objects representing their generic definitions.
9937 mono_loader_lock ();
9938 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9939 mono_loader_unlock ();
9942 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9945 #ifndef DISABLE_REFLECTION_EMIT
9948 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9950 MonoMethodInflated *imethod;
9951 MonoGenericContext *context;
9955 * With generic code sharing the klass might not be inflated.
9956 * This can happen because classes inflated with their own
9957 * type arguments are "normalized" to the uninflated class.
9959 if (!klass->generic_class)
9962 context = mono_class_get_context (klass);
9964 if (klass->method.count) {
9965 /* Find the already created inflated method */
9966 for (i = 0; i < klass->method.count; ++i) {
9967 g_assert (klass->methods [i]->is_inflated);
9968 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9971 g_assert (i < klass->method.count);
9972 imethod = (MonoMethodInflated*)klass->methods [i];
9974 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9977 if (method->is_generic && method->klass->image->dynamic) {
9978 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9980 mono_loader_lock ();
9981 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9982 mono_loader_unlock ();
9984 return (MonoMethod *) imethod;
9988 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9993 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
9995 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9996 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9997 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9999 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10000 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10001 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10002 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10003 method = ((MonoReflectionMethod *) obj)->method;
10005 method = NULL; /* prevent compiler warning */
10006 g_error ("can't handle type %s", obj->vtable->klass->name);
10009 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10012 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10014 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10015 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10018 MonoGenericClass *gclass;
10019 MonoDynamicGenericClass *dgclass;
10020 MonoClass *klass, *gklass;
10024 MONO_ARCH_SAVE_REGS;
10026 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10027 klass = mono_class_from_mono_type (gtype);
10028 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10029 gclass = gtype->data.generic_class;
10031 g_assert (gclass->is_dynamic);
10032 dgclass = (MonoDynamicGenericClass *) gclass;
10034 if (dgclass->initialized)
10037 gklass = gclass->container_class;
10038 mono_class_init (gklass);
10040 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10041 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10042 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10043 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10044 dgclass->count_events = events ? mono_array_length (events) : 0;
10046 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10047 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10048 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10049 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10050 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10051 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10052 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10054 for (i = 0; i < dgclass->count_methods; i++) {
10055 MonoObject *obj = mono_array_get (methods, gpointer, i);
10057 dgclass->methods [i] = inflate_method (type, obj);
10060 for (i = 0; i < dgclass->count_ctors; i++) {
10061 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10063 dgclass->ctors [i] = inflate_method (type, obj);
10066 for (i = 0; i < dgclass->count_fields; i++) {
10067 MonoObject *obj = mono_array_get (fields, gpointer, i);
10068 MonoClassField *field, *inflated_field = NULL;
10070 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10071 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10072 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10073 field = ((MonoReflectionField *) obj)->field;
10075 field = NULL; /* prevent compiler warning */
10076 g_assert_not_reached ();
10079 dgclass->fields [i] = *field;
10080 dgclass->fields [i].parent = klass;
10081 dgclass->fields [i].type = mono_class_inflate_generic_type (
10082 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10083 dgclass->field_generic_types [i] = field->type;
10084 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10085 dgclass->field_objects [i] = obj;
10087 if (inflated_field) {
10088 g_free (inflated_field);
10090 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10094 for (i = 0; i < dgclass->count_properties; i++) {
10095 MonoObject *obj = mono_array_get (properties, gpointer, i);
10096 MonoProperty *property = &dgclass->properties [i];
10098 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10099 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10101 property->parent = klass;
10102 property->attrs = pb->attrs;
10103 property->name = mono_string_to_utf8 (pb->name);
10104 if (pb->get_method)
10105 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10106 if (pb->set_method)
10107 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10108 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10109 *property = *((MonoReflectionProperty *) obj)->property;
10110 property->name = g_strdup (property->name);
10113 property->get = inflate_mono_method (klass, property->get, NULL);
10115 property->set = inflate_mono_method (klass, property->set, NULL);
10117 g_assert_not_reached ();
10120 for (i = 0; i < dgclass->count_events; i++) {
10121 MonoObject *obj = mono_array_get (events, gpointer, i);
10122 MonoEvent *event = &dgclass->events [i];
10124 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10125 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10127 event->parent = klass;
10128 event->attrs = eb->attrs;
10129 event->name = mono_string_to_utf8 (eb->name);
10130 if (eb->add_method)
10131 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10132 if (eb->remove_method)
10133 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10134 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10135 *event = *((MonoReflectionMonoEvent *) obj)->event;
10136 event->name = g_strdup (event->name);
10139 event->add = inflate_mono_method (klass, event->add, NULL);
10141 event->remove = inflate_mono_method (klass, event->remove, NULL);
10143 g_assert_not_reached ();
10146 dgclass->initialized = TRUE;
10150 ensure_generic_class_runtime_vtable (MonoClass *klass)
10152 MonoClass *gklass = klass->generic_class->container_class;
10155 if (klass->wastypebuilder)
10158 ensure_runtime_vtable (gklass);
10160 klass->method.count = gklass->method.count;
10161 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10163 for (i = 0; i < klass->method.count; i++) {
10164 klass->methods [i] = mono_class_inflate_generic_method_full (
10165 gklass->methods [i], klass, mono_class_get_context (klass));
10168 klass->interface_count = gklass->interface_count;
10169 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10170 for (i = 0; i < klass->interface_count; ++i) {
10171 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10172 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10173 mono_metadata_free_type (iface_type);
10175 ensure_runtime_vtable (klass->interfaces [i]);
10177 klass->interfaces_inited = 1;
10179 /*We can only finish with this klass once it's parent has as well*/
10180 if (gklass->wastypebuilder)
10181 klass->wastypebuilder = TRUE;
10186 ensure_runtime_vtable (MonoClass *klass)
10188 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10191 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10194 ensure_runtime_vtable (klass->parent);
10197 num = tb->ctors? mono_array_length (tb->ctors): 0;
10198 num += tb->num_methods;
10199 klass->method.count = num;
10200 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10201 num = tb->ctors? mono_array_length (tb->ctors): 0;
10202 for (i = 0; i < num; ++i)
10203 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10204 num = tb->num_methods;
10206 for (i = 0; i < num; ++i)
10207 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10209 if (tb->interfaces) {
10210 klass->interface_count = mono_array_length (tb->interfaces);
10211 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10212 for (i = 0; i < klass->interface_count; ++i) {
10213 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10214 klass->interfaces [i] = mono_class_from_mono_type (iface);
10215 ensure_runtime_vtable (klass->interfaces [i]);
10217 klass->interfaces_inited = 1;
10219 } else if (klass->generic_class){
10220 ensure_generic_class_runtime_vtable (klass);
10223 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10224 for (i = 0; i < klass->method.count; ++i)
10225 klass->methods [i]->slot = i;
10227 mono_class_setup_interface_offsets (klass);
10228 mono_class_setup_interface_id (klass);
10232 * The generic vtable is needed even if image->run is not set since some
10233 * runtime code like ves_icall_Type_GetMethodsByName depends on
10234 * method->slot being defined.
10238 * tb->methods could not be freed since it is used for determining
10239 * overrides during dynamic vtable construction.
10244 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10246 MonoReflectionTypeBuilder *tb;
10250 *num_overrides = 0;
10252 g_assert (klass->image->dynamic);
10254 if (!klass->reflection_info)
10257 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10259 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10263 for (i = 0; i < tb->num_methods; ++i) {
10264 MonoReflectionMethodBuilder *mb =
10265 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10266 if (mb->override_method)
10272 *overrides = g_new0 (MonoMethod*, onum * 2);
10275 for (i = 0; i < tb->num_methods; ++i) {
10276 MonoReflectionMethodBuilder *mb =
10277 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10278 if (mb->override_method) {
10279 (*overrides) [onum * 2] =
10280 mb->override_method->method;
10281 (*overrides) [onum * 2 + 1] =
10284 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10285 g_assert (mb->override_method->method);
10286 g_assert (mb->mhandle);
10293 *num_overrides = onum;
10297 typebuilder_setup_fields (MonoClass *klass)
10299 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10300 MonoReflectionFieldBuilder *fb;
10301 MonoClassField *field;
10302 MonoImage *image = klass->image;
10303 const char *p, *p2;
10305 guint32 len, idx, real_size = 0;
10307 klass->field.count = tb->num_fields;
10308 klass->field.first = 0;
10310 if (tb->class_size) {
10311 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10312 klass->packing_size = tb->packing_size;
10313 real_size = klass->instance_size + tb->class_size;
10316 if (!klass->field.count) {
10317 klass->instance_size = MAX (klass->instance_size, real_size);
10321 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10322 mono_class_alloc_ext (klass);
10323 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10325 for (i = 0; i < klass->field.count; ++i) {
10326 fb = mono_array_get (tb->fields, gpointer, i);
10327 field = &klass->fields [i];
10328 field->name = mono_string_to_utf8_image (image, fb->name);
10330 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10331 field->type->attrs = fb->attrs;
10333 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10335 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10336 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10337 if (fb->offset != -1)
10338 field->offset = fb->offset;
10339 field->parent = klass;
10340 fb->handle = field;
10341 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10343 if (fb->def_value) {
10344 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10345 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10346 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10347 /* Copy the data from the blob since it might get realloc-ed */
10348 p = assembly->blob.data + idx;
10349 len = mono_metadata_decode_blob_size (p, &p2);
10351 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10352 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10356 klass->instance_size = MAX (klass->instance_size, real_size);
10357 mono_class_layout_fields (klass);
10361 typebuilder_setup_properties (MonoClass *klass)
10363 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10364 MonoReflectionPropertyBuilder *pb;
10365 MonoImage *image = klass->image;
10366 MonoProperty *properties;
10370 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10372 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10373 klass->ext->property.first = 0;
10375 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10376 klass->ext->properties = properties;
10377 for (i = 0; i < klass->ext->property.count; ++i) {
10378 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10379 properties [i].parent = klass;
10380 properties [i].attrs = pb->attrs;
10381 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10382 if (pb->get_method)
10383 properties [i].get = pb->get_method->mhandle;
10384 if (pb->set_method)
10385 properties [i].set = pb->set_method->mhandle;
10387 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10391 MonoReflectionEvent *
10392 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10394 MonoEvent *event = g_new0 (MonoEvent, 1);
10398 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10400 event->parent = klass;
10401 event->attrs = eb->attrs;
10402 event->name = mono_string_to_utf8 (eb->name);
10403 if (eb->add_method)
10404 event->add = eb->add_method->mhandle;
10405 if (eb->remove_method)
10406 event->remove = eb->remove_method->mhandle;
10407 if (eb->raise_method)
10408 event->raise = eb->raise_method->mhandle;
10410 if (eb->other_methods) {
10411 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10412 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10413 MonoReflectionMethodBuilder *mb =
10414 mono_array_get (eb->other_methods,
10415 MonoReflectionMethodBuilder*, j);
10416 event->other [j] = mb->mhandle;
10420 return mono_event_get_object (mono_object_domain (tb), klass, event);
10424 typebuilder_setup_events (MonoClass *klass)
10426 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10427 MonoReflectionEventBuilder *eb;
10428 MonoImage *image = klass->image;
10433 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10435 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10436 klass->ext->event.first = 0;
10438 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10439 klass->ext->events = events;
10440 for (i = 0; i < klass->ext->event.count; ++i) {
10441 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10442 events [i].parent = klass;
10443 events [i].attrs = eb->attrs;
10444 events [i].name = mono_string_to_utf8_image (image, eb->name);
10445 if (eb->add_method)
10446 events [i].add = eb->add_method->mhandle;
10447 if (eb->remove_method)
10448 events [i].remove = eb->remove_method->mhandle;
10449 if (eb->raise_method)
10450 events [i].raise = eb->raise_method->mhandle;
10452 if (eb->other_methods) {
10453 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10454 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10455 MonoReflectionMethodBuilder *mb =
10456 mono_array_get (eb->other_methods,
10457 MonoReflectionMethodBuilder*, j);
10458 events [i].other [j] = mb->mhandle;
10461 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10466 remove_instantiations_of (gpointer key,
10468 gpointer user_data)
10470 MonoType *type = (MonoType*)key;
10471 MonoClass *klass = (MonoClass*)user_data;
10473 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10480 check_array_for_usertypes (MonoArray *arr)
10487 for (i = 0; i < mono_array_length (arr); ++i)
10488 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10491 MonoReflectionType*
10492 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10495 MonoDomain* domain;
10496 MonoReflectionType* res;
10499 MONO_ARCH_SAVE_REGS;
10501 domain = mono_object_domain (tb);
10502 klass = mono_class_from_mono_type (tb->type.type);
10505 * Check for user defined Type subclasses.
10507 RESOLVE_TYPE (tb->parent);
10508 check_array_for_usertypes (tb->interfaces);
10510 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10511 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10513 RESOLVE_TYPE (fb->type);
10514 check_array_for_usertypes (fb->modreq);
10515 check_array_for_usertypes (fb->modopt);
10516 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10517 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10522 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10523 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10525 RESOLVE_TYPE (mb->rtype);
10526 check_array_for_usertypes (mb->return_modreq);
10527 check_array_for_usertypes (mb->return_modopt);
10528 check_array_for_usertypes (mb->parameters);
10529 if (mb->param_modreq)
10530 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10531 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10532 if (mb->param_modopt)
10533 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10534 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10539 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10540 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10542 check_array_for_usertypes (mb->parameters);
10543 if (mb->param_modreq)
10544 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10545 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10546 if (mb->param_modopt)
10547 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10548 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10553 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10556 * we need to lock the domain because the lock will be taken inside
10557 * So, we need to keep the locking order correct.
10559 mono_loader_lock ();
10560 mono_domain_lock (domain);
10561 if (klass->wastypebuilder) {
10562 mono_domain_unlock (domain);
10563 mono_loader_unlock ();
10564 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10567 * Fields to set in klass:
10568 * the various flags: delegate/unicode/contextbound etc.
10570 klass->flags = tb->attrs;
10571 klass->has_cctor = 1;
10572 klass->has_finalize = 1;
10575 if (!((MonoDynamicImage*)klass->image)->run) {
10576 if (klass->generic_container) {
10577 /* FIXME: The code below can't handle generic classes */
10578 klass->wastypebuilder = TRUE;
10579 mono_loader_unlock ();
10580 mono_domain_unlock (domain);
10581 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10586 /* enums are done right away */
10587 if (!klass->enumtype)
10588 ensure_runtime_vtable (klass);
10590 if (tb->subtypes) {
10591 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10592 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10593 mono_class_alloc_ext (klass);
10594 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)));
10598 klass->nested_classes_inited = TRUE;
10600 /* fields and object layout */
10601 if (klass->parent) {
10602 if (!klass->parent->size_inited)
10603 mono_class_init (klass->parent);
10604 klass->instance_size = klass->parent->instance_size;
10605 klass->sizes.class_size = 0;
10606 klass->min_align = klass->parent->min_align;
10607 /* if the type has no fields we won't call the field_setup
10608 * routine which sets up klass->has_references.
10610 klass->has_references |= klass->parent->has_references;
10612 klass->instance_size = sizeof (MonoObject);
10613 klass->min_align = 1;
10616 /* FIXME: handle packing_size and instance_size */
10617 typebuilder_setup_fields (klass);
10619 typebuilder_setup_properties (klass);
10621 typebuilder_setup_events (klass);
10623 klass->wastypebuilder = TRUE;
10626 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10627 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10628 * we want to return normal System.MonoType objects, so clear these out from the cache.
10630 if (domain->type_hash && klass->generic_container)
10631 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10633 mono_domain_unlock (domain);
10634 mono_loader_unlock ();
10636 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10637 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10638 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10641 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10642 g_assert (res != (MonoReflectionType*)tb);
10648 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10650 MonoGenericParamFull *param;
10654 MONO_ARCH_SAVE_REGS;
10656 param = g_new0 (MonoGenericParamFull, 1);
10658 if (gparam->mbuilder) {
10659 if (!gparam->mbuilder->generic_container) {
10660 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10661 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10662 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10663 gparam->mbuilder->generic_container->is_method = TRUE;
10665 * Cannot set owner.method, since the MonoMethod is not created yet.
10666 * Set the image field instead, so type_in_image () works.
10668 gparam->mbuilder->generic_container->image = klass->image;
10670 param->param.owner = gparam->mbuilder->generic_container;
10671 } else if (gparam->tbuilder) {
10672 if (!gparam->tbuilder->generic_container) {
10673 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10674 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10675 gparam->tbuilder->generic_container->owner.klass = klass;
10677 param->param.owner = gparam->tbuilder->generic_container;
10680 param->info.name = mono_string_to_utf8 (gparam->name);
10681 param->param.num = gparam->index;
10683 image = &gparam->tbuilder->module->dynamic_image->image;
10684 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10686 gparam->type.type = &pklass->byval_arg;
10688 MOVING_GC_REGISTER (&pklass->reflection_info);
10689 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10690 mono_image_lock (image);
10691 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10692 mono_image_unlock (image);
10696 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10698 MonoReflectionModuleBuilder *module = sig->module;
10699 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10700 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10705 check_array_for_usertypes (sig->arguments);
10707 sigbuffer_init (&buf, 32);
10709 sigbuffer_add_value (&buf, 0x07);
10710 sigbuffer_add_value (&buf, na);
10711 if (assembly != NULL){
10712 for (i = 0; i < na; ++i) {
10713 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10714 encode_reflection_type (assembly, type, &buf);
10718 buflen = buf.p - buf.buf;
10719 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10720 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10721 sigbuffer_free (&buf);
10727 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10729 MonoDynamicImage *assembly = sig->module->dynamic_image;
10730 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10735 check_array_for_usertypes (sig->arguments);
10737 sigbuffer_init (&buf, 32);
10739 sigbuffer_add_value (&buf, 0x06);
10740 for (i = 0; i < na; ++i) {
10741 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10742 encode_reflection_type (assembly, type, &buf);
10745 buflen = buf.p - buf.buf;
10746 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10747 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10748 sigbuffer_free (&buf);
10754 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10756 ReflectionMethodBuilder rmb;
10757 MonoMethodSignature *sig;
10762 sig = dynamic_method_to_signature (mb);
10764 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10767 * Resolve references.
10770 * Every second entry in the refs array is reserved for storing handle_class,
10771 * which is needed by the ldtoken implementation in the JIT.
10773 rmb.nrefs = mb->nrefs;
10774 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10775 for (i = 0; i < mb->nrefs; i += 2) {
10776 MonoClass *handle_class;
10778 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10780 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10781 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10783 * The referenced DynamicMethod should already be created by the managed
10784 * code, except in the case of circular references. In that case, we store
10785 * method in the refs array, and fix it up later when the referenced
10786 * DynamicMethod is created.
10788 if (method->mhandle) {
10789 ref = method->mhandle;
10791 /* FIXME: GC object stored in unmanaged memory */
10794 /* FIXME: GC object stored in unmanaged memory */
10795 method->referenced_by = g_slist_append (method->referenced_by, mb);
10797 handle_class = mono_defaults.methodhandle_class;
10799 MonoException *ex = NULL;
10800 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10802 ex = mono_get_exception_type_load (NULL, NULL);
10803 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10804 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10808 mono_raise_exception (ex);
10813 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10814 rmb.refs [i + 1] = handle_class;
10817 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10819 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10821 /* Fix up refs entries pointing at us */
10822 for (l = mb->referenced_by; l; l = l->next) {
10823 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10824 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10827 g_assert (method->mhandle);
10829 data = (gpointer*)wrapper->method_data;
10830 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10831 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10832 data [i + 1] = mb->mhandle;
10835 g_slist_free (mb->referenced_by);
10839 /* ilgen is no longer needed */
10843 #endif /* DISABLE_REFLECTION_EMIT */
10846 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10851 mono_runtime_free_method (
10852 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10857 * mono_reflection_is_valid_dynamic_token:
10859 * Returns TRUE if token is valid.
10863 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10865 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10868 #ifndef DISABLE_REFLECTION_EMIT
10871 * mono_reflection_lookup_dynamic_token:
10873 * Finish the Builder object pointed to by TOKEN and return the corresponding
10874 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10875 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10878 * LOCKING: Take the loader lock
10881 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10883 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10887 mono_loader_lock ();
10888 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10889 mono_loader_unlock ();
10892 g_error ("Could not find required dynamic token 0x%08x", token);
10898 handle_class = &klass;
10899 return resolve_object (image, obj, handle_class, context);
10903 * ensure_complete_type:
10905 * Ensure that KLASS is completed if it is a dynamic type, or references
10909 ensure_complete_type (MonoClass *klass)
10911 if (klass->image->dynamic && !klass->wastypebuilder) {
10912 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10914 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10916 // Asserting here could break a lot of code
10917 //g_assert (klass->wastypebuilder);
10920 if (klass->generic_class) {
10921 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10924 for (i = 0; i < inst->type_argc; ++i) {
10925 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10931 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10933 gpointer result = NULL;
10935 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10936 result = mono_string_intern ((MonoString*)obj);
10937 *handle_class = NULL;
10939 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10940 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
10942 MonoType *inflated = mono_class_inflate_generic_type (type, context);
10943 result = mono_class_from_mono_type (inflated);
10944 mono_metadata_free_type (inflated);
10946 result = mono_class_from_mono_type (type);
10948 *handle_class = mono_defaults.typehandle_class;
10950 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10951 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10952 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10953 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10954 result = ((MonoReflectionMethod*)obj)->method;
10956 result = mono_class_inflate_generic_method (result, context);
10957 *handle_class = mono_defaults.methodhandle_class;
10959 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10960 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10961 result = mb->mhandle;
10963 /* Type is not yet created */
10964 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10966 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10969 * Hopefully this has been filled in by calling CreateType() on the
10973 * TODO: This won't work if the application finishes another
10974 * TypeBuilder instance instead of this one.
10976 result = mb->mhandle;
10979 result = mono_class_inflate_generic_method (result, context);
10980 *handle_class = mono_defaults.methodhandle_class;
10981 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10982 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10984 result = cb->mhandle;
10986 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10988 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10989 result = cb->mhandle;
10992 result = mono_class_inflate_generic_method (result, context);
10993 *handle_class = mono_defaults.methodhandle_class;
10994 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10995 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10997 ensure_complete_type (field->parent);
10999 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11000 MonoClass *class = mono_class_from_mono_type (inflated);
11001 MonoClassField *inflated_field;
11002 gpointer iter = NULL;
11003 mono_metadata_free_type (inflated);
11004 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11005 if (!strcmp (field->name, inflated_field->name))
11008 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11009 result = inflated_field;
11013 *handle_class = mono_defaults.fieldhandle_class;
11015 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11016 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11017 result = fb->handle;
11020 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11022 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11023 result = fb->handle;
11026 if (fb->handle && fb->handle->parent->generic_container) {
11027 MonoClass *klass = fb->handle->parent;
11028 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11029 MonoClass *inflated = mono_class_from_mono_type (type);
11031 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11033 mono_metadata_free_type (type);
11035 *handle_class = mono_defaults.fieldhandle_class;
11036 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11037 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11038 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11041 klass = type->data.klass;
11042 if (klass->wastypebuilder) {
11043 /* Already created */
11047 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11048 result = type->data.klass;
11051 *handle_class = mono_defaults.typehandle_class;
11052 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11053 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11054 MonoMethodSignature *sig;
11057 if (helper->arguments)
11058 nargs = mono_array_length (helper->arguments);
11062 sig = mono_metadata_signature_alloc (image, nargs);
11063 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11064 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11066 if (helper->call_conv == 0) /* unmanaged */
11067 sig->call_convention = helper->unmanaged_call_conv - 1;
11069 if (helper->call_conv & 0x02)
11070 sig->call_convention = MONO_CALL_VARARG;
11072 sig->call_convention = MONO_CALL_DEFAULT;
11074 sig->param_count = nargs;
11075 /* TODO: Copy type ? */
11076 sig->ret = helper->return_type->type;
11077 for (i = 0; i < nargs; ++i)
11078 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11081 *handle_class = NULL;
11082 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11083 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11084 /* Already created by the managed code */
11085 g_assert (method->mhandle);
11086 result = method->mhandle;
11087 *handle_class = mono_defaults.methodhandle_class;
11088 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11089 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11090 type = mono_class_inflate_generic_type (type, context);
11091 result = mono_class_from_mono_type (type);
11092 *handle_class = mono_defaults.typehandle_class;
11094 mono_metadata_free_type (type);
11095 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11096 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11097 type = mono_class_inflate_generic_type (type, context);
11098 result = mono_class_from_mono_type (type);
11099 *handle_class = mono_defaults.typehandle_class;
11101 mono_metadata_free_type (type);
11102 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11103 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11104 MonoClass *inflated;
11107 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11108 inflated = mono_class_from_mono_type (type);
11110 g_assert (f->fb->handle);
11111 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11113 mono_metadata_free_type (type);
11114 *handle_class = mono_defaults.fieldhandle_class;
11115 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11116 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11117 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11118 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11119 g_assert (c->cb->mhandle);
11120 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11121 *handle_class = mono_defaults.methodhandle_class;
11122 mono_metadata_free_type (type);
11123 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11124 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11125 if (m->method_args) {
11126 result = mono_reflection_method_on_tb_inst_get_handle (m);
11128 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11129 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11130 g_assert (m->mb->mhandle);
11131 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11132 mono_metadata_free_type (type);
11134 *handle_class = mono_defaults.methodhandle_class;
11135 } else if (is_sre_array (mono_object_get_class(obj)) ||
11136 is_sre_byref (mono_object_get_class(obj)) ||
11137 is_sre_pointer (mono_object_get_class(obj))) {
11138 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11139 MonoType *type = mono_reflection_type_get_handle (ref_type);
11140 result = mono_class_from_mono_type (type);
11141 *handle_class = mono_defaults.typehandle_class;
11143 g_print ("%s\n", obj->vtable->klass->name);
11144 g_assert_not_reached ();
11149 #else /* DISABLE_REFLECTION_EMIT */
11152 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11154 g_assert_not_reached ();
11159 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11161 g_assert_not_reached ();
11165 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11167 g_assert_not_reached ();
11171 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11173 g_assert_not_reached ();
11177 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11179 g_assert_not_reached ();
11183 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11185 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11189 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11191 g_assert_not_reached ();
11195 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11197 g_assert_not_reached ();
11200 MonoReflectionModule *
11201 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11203 g_assert_not_reached ();
11208 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11210 g_assert_not_reached ();
11215 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11217 g_assert_not_reached ();
11222 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11223 gboolean create_methodspec, gboolean register_token)
11225 g_assert_not_reached ();
11230 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11235 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11236 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11239 g_assert_not_reached ();
11243 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11246 *num_overrides = 0;
11249 MonoReflectionEvent *
11250 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11252 g_assert_not_reached ();
11256 MonoReflectionType*
11257 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11259 g_assert_not_reached ();
11264 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11266 g_assert_not_reached ();
11270 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11272 g_assert_not_reached ();
11277 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11279 g_assert_not_reached ();
11284 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11289 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11295 mono_reflection_type_get_handle (MonoReflectionType* ref)
11302 #endif /* DISABLE_REFLECTION_EMIT */
11304 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11305 const static guint32 declsec_flags_map[] = {
11306 0x00000000, /* empty */
11307 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11308 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11309 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11310 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11311 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11312 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11313 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11314 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11315 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11316 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11317 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11318 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11319 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11320 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11321 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11322 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11323 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11324 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11328 * Returns flags that includes all available security action associated to the handle.
11329 * @token: metadata token (either for a class or a method)
11330 * @image: image where resides the metadata.
11333 mono_declsec_get_flags (MonoImage *image, guint32 token)
11335 int index = mono_metadata_declsec_from_index (image, token);
11336 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11337 guint32 result = 0;
11341 /* HasSecurity can be present for other, not specially encoded, attributes,
11342 e.g. SuppressUnmanagedCodeSecurityAttribute */
11346 for (i = index; i < t->rows; i++) {
11347 guint32 cols [MONO_DECL_SECURITY_SIZE];
11349 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11350 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11353 action = cols [MONO_DECL_SECURITY_ACTION];
11354 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11355 result |= declsec_flags_map [action];
11357 g_assert_not_reached ();
11364 * Get the security actions (in the form of flags) associated with the specified method.
11366 * @method: The method for which we want the declarative security flags.
11367 * Return the declarative security flags for the method (only).
11369 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11370 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11373 mono_declsec_flags_from_method (MonoMethod *method)
11375 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11376 /* FIXME: No cache (for the moment) */
11377 guint32 idx = mono_method_get_index (method);
11378 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11379 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11380 return mono_declsec_get_flags (method->klass->image, idx);
11386 * Get the security actions (in the form of flags) associated with the specified class.
11388 * @klass: The class for which we want the declarative security flags.
11389 * Return the declarative security flags for the class.
11391 * Note: We cache the flags inside the MonoClass structure as this will get
11392 * called very often (at least for each method).
11395 mono_declsec_flags_from_class (MonoClass *klass)
11397 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11398 if (!klass->ext || !klass->ext->declsec_flags) {
11401 idx = mono_metadata_token_index (klass->type_token);
11402 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11403 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11404 mono_loader_lock ();
11405 mono_class_alloc_ext (klass);
11406 mono_loader_unlock ();
11407 /* we cache the flags on classes */
11408 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11410 return klass->ext->declsec_flags;
11416 * Get the security actions (in the form of flags) associated with the specified assembly.
11418 * @assembly: The assembly for which we want the declarative security flags.
11419 * Return the declarative security flags for the assembly.
11422 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11424 guint32 idx = 1; /* there is only one assembly */
11425 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11426 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11427 return mono_declsec_get_flags (assembly->image, idx);
11432 * Fill actions for the specific index (which may either be an encoded class token or
11433 * an encoded method token) from the metadata image.
11434 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11437 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11438 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11440 MonoBoolean result = FALSE;
11442 guint32 cols [MONO_DECL_SECURITY_SIZE];
11443 int index = mono_metadata_declsec_from_index (image, token);
11446 t = &image->tables [MONO_TABLE_DECLSECURITY];
11447 for (i = index; i < t->rows; i++) {
11448 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11450 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11453 /* if present only replace (class) permissions with method permissions */
11454 /* if empty accept either class or method permissions */
11455 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11456 if (!actions->demand.blob) {
11457 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11458 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11459 actions->demand.blob = (char*) (blob + 2);
11460 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11463 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11464 if (!actions->noncasdemand.blob) {
11465 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11466 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11467 actions->noncasdemand.blob = (char*) (blob + 2);
11468 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11471 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11472 if (!actions->demandchoice.blob) {
11473 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11474 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11475 actions->demandchoice.blob = (char*) (blob + 2);
11476 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11486 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11487 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11489 guint32 idx = mono_metadata_token_index (klass->type_token);
11490 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11491 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11492 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11496 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11497 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11499 guint32 idx = mono_method_get_index (method);
11500 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11501 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11502 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11506 * Collect all actions (that requires to generate code in mini) assigned for
11507 * the specified method.
11508 * Note: Don't use the content of actions if the function return FALSE.
11511 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11513 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11514 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11515 MonoBoolean result = FALSE;
11518 /* quick exit if no declarative security is present in the metadata */
11519 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11522 /* we want the original as the wrapper is "free" of the security informations */
11523 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11524 method = mono_marshal_method_from_wrapper (method);
11529 /* First we look for method-level attributes */
11530 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11531 mono_class_init (method->klass);
11532 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11534 result = mono_declsec_get_method_demands_params (method, demands,
11535 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11538 /* Here we use (or create) the class declarative cache to look for demands */
11539 flags = mono_declsec_flags_from_class (method->klass);
11540 if (flags & mask) {
11542 mono_class_init (method->klass);
11543 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11545 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11546 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11549 /* The boolean return value is used as a shortcut in case nothing needs to
11550 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11556 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11558 * Note: Don't use the content of actions if the function return FALSE.
11561 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11563 MonoBoolean result = FALSE;
11566 /* quick exit if no declarative security is present in the metadata */
11567 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11570 /* we want the original as the wrapper is "free" of the security informations */
11571 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11572 method = mono_marshal_method_from_wrapper (method);
11577 /* results are independant - zeroize both */
11578 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11579 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11581 /* First we look for method-level attributes */
11582 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11583 mono_class_init (method->klass);
11585 result = mono_declsec_get_method_demands_params (method, cmethod,
11586 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11589 /* Here we use (or create) the class declarative cache to look for demands */
11590 flags = mono_declsec_flags_from_class (method->klass);
11591 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11592 mono_class_init (method->klass);
11594 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11595 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11602 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11604 * @klass The inherited class - this is the class that provides the security check (attributes)
11606 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11608 * Note: Don't use the content of actions if the function return FALSE.
11611 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11613 MonoBoolean result = FALSE;
11616 /* quick exit if no declarative security is present in the metadata */
11617 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11620 /* Here we use (or create) the class declarative cache to look for demands */
11621 flags = mono_declsec_flags_from_class (klass);
11622 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11623 mono_class_init (klass);
11624 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11626 result |= mono_declsec_get_class_demands_params (klass, demands,
11627 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11634 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11636 * Note: Don't use the content of actions if the function return FALSE.
11639 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11641 /* quick exit if no declarative security is present in the metadata */
11642 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11645 /* we want the original as the wrapper is "free" of the security informations */
11646 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11647 method = mono_marshal_method_from_wrapper (method);
11652 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11653 mono_class_init (method->klass);
11654 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11656 return mono_declsec_get_method_demands_params (method, demands,
11657 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11664 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11666 guint32 cols [MONO_DECL_SECURITY_SIZE];
11670 int index = mono_metadata_declsec_from_index (image, token);
11674 t = &image->tables [MONO_TABLE_DECLSECURITY];
11675 for (i = index; i < t->rows; i++) {
11676 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11678 /* shortcut - index are ordered */
11679 if (token != cols [MONO_DECL_SECURITY_PARENT])
11682 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11683 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11684 entry->blob = (char*) (metadata + 2);
11685 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11694 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11696 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11697 guint32 idx = mono_method_get_index (method);
11698 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11699 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11700 return get_declsec_action (method->klass->image, idx, action, entry);
11706 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11709 guint32 flags = mono_declsec_flags_from_class (klass);
11710 if (declsec_flags_map [action] & flags) {
11711 guint32 idx = mono_metadata_token_index (klass->type_token);
11712 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11713 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11714 return get_declsec_action (klass->image, idx, action, entry);
11720 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11722 guint32 idx = 1; /* there is only one assembly */
11723 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11724 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11726 return get_declsec_action (assembly->image, idx, action, entry);
11730 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11732 MonoObject *res, *exc;
11734 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11735 static MonoMethod *method = NULL;
11737 if (!System_Reflection_Emit_TypeBuilder) {
11738 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11739 g_assert (System_Reflection_Emit_TypeBuilder);
11741 if (method == NULL) {
11742 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11747 * The result of mono_type_get_object () might be a System.MonoType but we
11748 * need a TypeBuilder so use klass->reflection_info.
11750 g_assert (klass->reflection_info);
11751 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11753 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11755 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11759 return *(MonoBoolean*)mono_object_unbox (res);