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 local_var_sig_token = 0;
6699 case METHOD_HEADER_FAT_FORMAT:
6703 local_var_sig_token = read32 (ptr);
6706 g_assert_not_reached ();
6709 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6711 ret->init_locals = header->init_locals;
6712 ret->max_stack = header->max_stack;
6713 ret->local_var_sig_token = local_var_sig_token;
6714 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6715 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6718 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6719 for (i = 0; i < header->num_locals; ++i) {
6720 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6721 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6722 info->is_pinned = header->locals [i]->pinned;
6723 info->local_index = i;
6724 mono_array_setref (ret->locals, i, info);
6728 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6729 for (i = 0; i < header->num_clauses; ++i) {
6730 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6731 MonoExceptionClause *clause = &header->clauses [i];
6733 info->flags = clause->flags;
6734 info->try_offset = clause->try_offset;
6735 info->try_length = clause->try_len;
6736 info->handler_offset = clause->handler_offset;
6737 info->handler_length = clause->handler_len;
6738 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6739 info->filter_offset = clause->data.filter_offset;
6740 else if (clause->data.catch_class)
6741 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6743 mono_array_setref (ret->clauses, i, info);
6746 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6751 * mono_get_dbnull_object:
6752 * @domain: Domain where the object lives
6754 * Returns the System.DBNull.Value singleton object
6756 * Used as the value for ParameterInfo.DefaultValue
6759 mono_get_dbnull_object (MonoDomain *domain)
6762 static MonoClassField *dbnull_value_field = NULL;
6764 if (!dbnull_value_field) {
6765 MonoClass *dbnull_klass;
6766 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6767 mono_class_init (dbnull_klass);
6768 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6769 g_assert (dbnull_value_field);
6771 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6777 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6779 guint32 param_index, i, lastp, crow = 0;
6780 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6783 MonoClass *klass = method->klass;
6784 MonoImage *image = klass->image;
6785 MonoMethodSignature *methodsig = mono_method_signature (method);
6787 MonoTableInfo *constt;
6788 MonoTableInfo *methodt;
6789 MonoTableInfo *paramt;
6791 if (!methodsig->param_count)
6794 mono_class_init (klass);
6796 if (klass->image->dynamic) {
6797 MonoReflectionMethodAux *aux;
6798 if (method->is_inflated)
6799 method = ((MonoMethodInflated*)method)->declaring;
6800 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6801 if (aux && aux->param_defaults) {
6802 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6803 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6808 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6809 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6810 constt = &image->tables [MONO_TABLE_CONSTANT];
6812 idx = mono_method_get_index (method) - 1;
6813 g_assert (idx != -1);
6815 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6816 if (idx + 1 < methodt->rows)
6817 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6819 lastp = paramt->rows + 1;
6821 for (i = param_index; i < lastp; ++i) {
6824 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6825 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6827 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6830 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6835 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6836 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6837 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6844 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6849 MonoType *basetype = type;
6854 klass = mono_class_from_mono_type (type);
6855 if (klass->valuetype) {
6856 object = mono_object_new (domain, klass);
6857 retval = ((gchar *) object + sizeof (MonoObject));
6858 if (klass->enumtype)
6859 basetype = mono_class_enum_basetype (klass);
6864 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6871 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6875 memset (assembly, 0, sizeof (MonoAssemblyName));
6877 assembly->culture = "";
6878 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6880 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6883 while (g_ascii_isspace (*p) || *p == ',') {
6892 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6894 assembly->major = strtoul (p, &s, 10);
6895 if (s == p || *s != '.')
6898 assembly->minor = strtoul (p, &s, 10);
6899 if (s == p || *s != '.')
6902 assembly->build = strtoul (p, &s, 10);
6903 if (s == p || *s != '.')
6906 assembly->revision = strtoul (p, &s, 10);
6910 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6912 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6913 assembly->culture = "";
6916 assembly->culture = p;
6917 while (*p && *p != ',') {
6921 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6923 if (strncmp (p, "null", 4) == 0) {
6928 while (*p && *p != ',') {
6931 len = (p - start + 1);
6932 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6933 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6934 g_strlcpy ((char*)assembly->public_key_token, start, len);
6937 while (*p && *p != ',')
6941 while (g_ascii_isspace (*p) || *p == ',') {
6955 * mono_reflection_parse_type:
6958 * Parse a type name as accepted by the GetType () method and output the info
6959 * extracted in the info structure.
6960 * the name param will be mangled, so, make a copy before passing it to this function.
6961 * The fields in info will be valid until the memory pointed to by name is valid.
6963 * See also mono_type_get_name () below.
6965 * Returns: 0 on parse error.
6968 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6969 MonoTypeNameParse *info)
6971 char *start, *p, *w, *temp, *last_point, *startn;
6972 int in_modifiers = 0;
6973 int isbyref = 0, rank, arity = 0, i;
6975 start = p = w = name;
6977 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6978 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6979 info->name = info->name_space = NULL;
6980 info->nested = NULL;
6981 info->modifiers = NULL;
6982 info->type_arguments = NULL;
6984 /* last_point separates the namespace from the name */
6987 while (*p == ' ') p++, start++, w++, name++;
6992 *p = 0; /* NULL terminate the name */
6994 info->nested = g_list_append (info->nested, startn);
6995 /* we have parsed the nesting namespace + name */
6999 info->name_space = start;
7001 info->name = last_point + 1;
7003 info->name_space = (char *)"";
7022 i = strtol (p, &temp, 10);
7039 info->name_space = start;
7041 info->name = last_point + 1;
7043 info->name_space = (char *)"";
7050 if (isbyref) /* only one level allowed by the spec */
7053 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7057 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7063 info->type_arguments = g_ptr_array_new ();
7064 for (i = 0; i < arity; i++) {
7065 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7066 gboolean fqname = FALSE;
7068 g_ptr_array_add (info->type_arguments, subinfo);
7075 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7086 while (*p && (*p != ']'))
7094 if (g_ascii_isspace (*aname)) {
7101 !assembly_name_to_aname (&subinfo->assembly, aname))
7105 if (i + 1 < arity) {
7125 else if (*p == '*') /* '*' means unknown lower bound */
7126 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7133 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7144 if (g_ascii_isspace (*p)) {
7151 return 0; /* missing assembly name */
7152 if (!assembly_name_to_aname (&info->assembly, p))
7158 if (info->assembly.name)
7161 // *w = 0; /* terminate class name */
7163 if (!info->name || !*info->name)
7167 /* add other consistency checks */
7172 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7174 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7178 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7180 gboolean type_resolve = FALSE;
7182 MonoImage *rootimage = image;
7184 if (info->assembly.name) {
7185 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7186 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7188 * This could happen in the AOT compiler case when the search hook is not
7191 assembly = image->assembly;
7193 /* then we must load the assembly ourselve - see #60439 */
7194 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7198 image = assembly->image;
7199 } else if (!image) {
7200 image = mono_defaults.corlib;
7203 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7204 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7205 image = mono_defaults.corlib;
7206 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7213 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7218 gboolean bounded = FALSE;
7221 image = mono_defaults.corlib;
7224 klass = mono_class_from_name_case (image, info->name_space, info->name);
7226 klass = mono_class_from_name (image, info->name_space, info->name);
7229 for (mod = info->nested; mod; mod = mod->next) {
7230 gpointer iter = NULL;
7234 mono_class_init (parent);
7236 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7238 if (g_strcasecmp (klass->name, mod->data) == 0)
7241 if (strcmp (klass->name, mod->data) == 0)
7250 mono_class_init (klass);
7252 if (info->type_arguments) {
7253 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7254 MonoReflectionType *the_type;
7258 for (i = 0; i < info->type_arguments->len; i++) {
7259 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7261 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7262 if (!type_args [i]) {
7268 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7270 instance = mono_reflection_bind_generic_parameters (
7271 the_type, info->type_arguments->len, type_args);
7277 klass = mono_class_from_mono_type (instance);
7280 for (mod = info->modifiers; mod; mod = mod->next) {
7281 modval = GPOINTER_TO_UINT (mod->data);
7282 if (!modval) { /* byref: must be last modifier */
7283 return &klass->this_arg;
7284 } else if (modval == -1) {
7285 klass = mono_ptr_class_get (&klass->byval_arg);
7286 } else if (modval == -2) {
7288 } else { /* array rank */
7289 klass = mono_bounded_array_class_get (klass, modval, bounded);
7291 mono_class_init (klass);
7294 return &klass->byval_arg;
7298 * mono_reflection_get_type:
7299 * @image: a metadata context
7300 * @info: type description structure
7301 * @ignorecase: flag for case-insensitive string compares
7302 * @type_resolve: whenever type resolve was already tried
7304 * Build a MonoType from the type description in @info.
7309 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7310 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7314 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7316 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7320 g_assert (assembly->dynamic);
7322 /* Enumerate all modules */
7325 if (abuilder->modules) {
7326 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7327 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7328 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7334 if (!type && abuilder->loaded_modules) {
7335 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7336 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7337 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7347 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7350 MonoReflectionAssembly *assembly;
7354 if (image && image->dynamic)
7355 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7357 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7360 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7367 *type_resolve = TRUE;
7370 /* Reconstruct the type name */
7371 fullName = g_string_new ("");
7372 if (info->name_space && (info->name_space [0] != '\0'))
7373 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7375 g_string_printf (fullName, "%s", info->name);
7376 for (mod = info->nested; mod; mod = mod->next)
7377 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7379 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7381 if (assembly->assembly->dynamic)
7382 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7384 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7387 g_string_free (fullName, TRUE);
7392 mono_reflection_free_type_info (MonoTypeNameParse *info)
7394 g_list_free (info->modifiers);
7395 g_list_free (info->nested);
7397 if (info->type_arguments) {
7400 for (i = 0; i < info->type_arguments->len; i++) {
7401 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7403 mono_reflection_free_type_info (subinfo);
7404 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7408 g_ptr_array_free (info->type_arguments, TRUE);
7413 * mono_reflection_type_from_name:
7415 * @image: a metadata context (can be NULL).
7417 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7418 * it defaults to get the type from @image or, if @image is NULL or loading
7419 * from it fails, uses corlib.
7423 mono_reflection_type_from_name (char *name, MonoImage *image)
7425 MonoType *type = NULL;
7426 MonoTypeNameParse info;
7429 /* Make a copy since parse_type modifies its argument */
7430 tmp = g_strdup (name);
7432 /*g_print ("requested type %s\n", str);*/
7433 if (mono_reflection_parse_type (tmp, &info)) {
7434 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7438 mono_reflection_free_type_info (&info);
7443 * mono_reflection_get_token:
7445 * Return the metadata token of OBJ which should be an object
7446 * representing a metadata element.
7449 mono_reflection_get_token (MonoObject *obj)
7454 klass = obj->vtable->klass;
7456 if (strcmp (klass->name, "MethodBuilder") == 0) {
7457 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7459 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7460 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7461 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7463 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7464 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7465 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7467 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7468 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7469 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7470 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7471 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7472 } else if (strcmp (klass->name, "MonoType") == 0) {
7473 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7474 token = mono_class_from_mono_type (type)->type_token;
7475 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7476 strcmp (klass->name, "MonoMethod") == 0 ||
7477 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7478 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7479 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7480 if (m->method->is_inflated) {
7481 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7482 return inflated->declaring->token;
7484 token = m->method->token;
7486 } else if (strcmp (klass->name, "MonoField") == 0) {
7487 MonoReflectionField *f = (MonoReflectionField*)obj;
7489 if (is_field_on_inst (f->field)) {
7490 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7491 int field_index = f->field - dgclass->fields;
7494 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7495 obj = dgclass->field_objects [field_index];
7496 return mono_reflection_get_token (obj);
7498 token = mono_class_get_field_token (f->field);
7499 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7500 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7502 token = mono_class_get_property_token (p->property);
7503 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7504 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7506 token = mono_class_get_event_token (p->event);
7507 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7508 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7510 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7511 } else if (strcmp (klass->name, "Module") == 0) {
7512 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7515 } else if (strcmp (klass->name, "Assembly") == 0) {
7516 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7518 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7519 MonoException *ex = mono_get_exception_not_implemented (msg);
7521 mono_raise_exception (ex);
7528 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7530 int slen, type = t->type;
7531 MonoClass *tklass = t->data.klass;
7537 case MONO_TYPE_BOOLEAN: {
7538 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7543 case MONO_TYPE_CHAR:
7545 case MONO_TYPE_I2: {
7546 guint16 *val = g_malloc (sizeof (guint16));
7551 #if SIZEOF_VOID_P == 4
7557 case MONO_TYPE_I4: {
7558 guint32 *val = g_malloc (sizeof (guint32));
7563 #if SIZEOF_VOID_P == 8
7564 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7568 case MONO_TYPE_I8: {
7569 guint64 *val = g_malloc (sizeof (guint64));
7574 case MONO_TYPE_R8: {
7575 double *val = g_malloc (sizeof (double));
7580 case MONO_TYPE_VALUETYPE:
7581 if (t->data.klass->enumtype) {
7582 type = mono_class_enum_basetype (t->data.klass)->type;
7585 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7588 case MONO_TYPE_STRING:
7589 if (*p == (char)0xFF) {
7593 slen = mono_metadata_decode_value (p, &p);
7595 return mono_string_new_len (mono_domain_get (), p, slen);
7596 case MONO_TYPE_CLASS: {
7599 if (*p == (char)0xFF) {
7604 slen = mono_metadata_decode_value (p, &p);
7605 n = g_memdup (p, slen + 1);
7607 t = mono_reflection_type_from_name (n, image);
7609 g_warning ("Cannot load type '%s'", n);
7613 return mono_type_get_object (mono_domain_get (), t);
7617 case MONO_TYPE_OBJECT: {
7620 MonoClass *subc = NULL;
7625 } else if (subt == 0x0E) {
7626 type = MONO_TYPE_STRING;
7628 } else if (subt == 0x1D) {
7629 MonoType simple_type = {{0}};
7634 /* See Partition II, Appendix B3 */
7635 etype = MONO_TYPE_OBJECT;
7636 type = MONO_TYPE_SZARRAY;
7637 simple_type.type = etype;
7638 tklass = mono_class_from_mono_type (&simple_type);
7640 } else if (subt == 0x55) {
7643 slen = mono_metadata_decode_value (p, &p);
7644 n = g_memdup (p, slen + 1);
7646 t = mono_reflection_type_from_name (n, image);
7648 g_error ("Cannot load type '%s'", n);
7651 subc = mono_class_from_mono_type (t);
7652 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7653 MonoType simple_type = {{0}};
7654 simple_type.type = subt;
7655 subc = mono_class_from_mono_type (&simple_type);
7657 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7659 val = load_cattr_value (image, &subc->byval_arg, p, end);
7660 obj = mono_object_new (mono_domain_get (), subc);
7661 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7665 case MONO_TYPE_SZARRAY: {
7667 guint32 i, alen, basetype;
7670 if (alen == 0xffffffff) {
7674 arr = mono_array_new (mono_domain_get(), tklass, alen);
7675 basetype = tklass->byval_arg.type;
7676 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7677 basetype = mono_class_enum_basetype (tklass)->type;
7682 case MONO_TYPE_BOOLEAN:
7683 for (i = 0; i < alen; i++) {
7684 MonoBoolean val = *p++;
7685 mono_array_set (arr, MonoBoolean, i, val);
7688 case MONO_TYPE_CHAR:
7691 for (i = 0; i < alen; i++) {
7692 guint16 val = read16 (p);
7693 mono_array_set (arr, guint16, i, val);
7700 for (i = 0; i < alen; i++) {
7701 guint32 val = read32 (p);
7702 mono_array_set (arr, guint32, i, val);
7707 for (i = 0; i < alen; i++) {
7710 mono_array_set (arr, double, i, val);
7716 for (i = 0; i < alen; i++) {
7717 guint64 val = read64 (p);
7718 mono_array_set (arr, guint64, i, val);
7722 case MONO_TYPE_CLASS:
7723 case MONO_TYPE_OBJECT:
7724 case MONO_TYPE_STRING:
7725 for (i = 0; i < alen; i++) {
7726 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7727 mono_array_setref (arr, i, item);
7731 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7737 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7743 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7745 static MonoClass *klass;
7746 static MonoMethod *ctor;
7748 void *params [2], *unboxed;
7751 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7753 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7755 params [0] = mono_type_get_object (mono_domain_get (), t);
7757 retval = mono_object_new (mono_domain_get (), klass);
7758 unboxed = mono_object_unbox (retval);
7759 mono_runtime_invoke (ctor, unboxed, params, NULL);
7765 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7767 static MonoClass *klass;
7768 static MonoMethod *ctor;
7770 void *unboxed, *params [2];
7773 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7775 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7778 params [1] = typedarg;
7779 retval = mono_object_new (mono_domain_get (), klass);
7780 unboxed = mono_object_unbox (retval);
7781 mono_runtime_invoke (ctor, unboxed, params, NULL);
7787 type_is_reference (MonoType *type)
7789 switch (type->type) {
7790 case MONO_TYPE_BOOLEAN:
7791 case MONO_TYPE_CHAR:
7804 case MONO_TYPE_VALUETYPE:
7812 free_param_data (MonoMethodSignature *sig, void **params) {
7814 for (i = 0; i < sig->param_count; ++i) {
7815 if (!type_is_reference (sig->params [i]))
7816 g_free (params [i]);
7821 * Find the field index in the metadata FieldDef table.
7824 find_field_index (MonoClass *klass, MonoClassField *field) {
7827 for (i = 0; i < klass->field.count; ++i) {
7828 if (field == &klass->fields [i])
7829 return klass->field.first + 1 + i;
7835 * Find the property index in the metadata Property table.
7838 find_property_index (MonoClass *klass, MonoProperty *property) {
7841 for (i = 0; i < klass->ext->property.count; ++i) {
7842 if (property == &klass->ext->properties [i])
7843 return klass->ext->property.first + 1 + i;
7849 * Find the event index in the metadata Event table.
7852 find_event_index (MonoClass *klass, MonoEvent *event) {
7855 for (i = 0; i < klass->ext->event.count; ++i) {
7856 if (event == &klass->ext->events [i])
7857 return klass->ext->event.first + 1 + i;
7863 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7865 const char *p = (const char*)data;
7867 guint32 i, j, num_named;
7869 void *params_buf [32];
7871 MonoMethodSignature *sig;
7873 mono_class_init (method->klass);
7876 attr = mono_object_new (mono_domain_get (), method->klass);
7877 mono_runtime_invoke (method, attr, NULL, NULL);
7881 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7884 /*g_print ("got attr %s\n", method->klass->name);*/
7886 sig = mono_method_signature (method);
7887 if (sig->param_count < 32)
7888 params = params_buf;
7890 /* Allocate using GC so it gets GC tracking */
7891 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7895 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7896 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7900 attr = mono_object_new (mono_domain_get (), method->klass);
7901 mono_runtime_invoke (method, attr, params, NULL);
7902 free_param_data (method->signature, params);
7903 num_named = read16 (named);
7905 for (j = 0; j < num_named; j++) {
7907 char *name, named_type, data_type;
7908 named_type = *named++;
7909 data_type = *named++; /* type of data */
7910 if (data_type == MONO_TYPE_SZARRAY)
7911 data_type = *named++;
7912 if (data_type == MONO_TYPE_ENUM) {
7915 type_len = mono_metadata_decode_blob_size (named, &named);
7916 type_name = g_malloc (type_len + 1);
7917 memcpy (type_name, named, type_len);
7918 type_name [type_len] = 0;
7920 /* FIXME: lookup the type and check type consistency */
7923 name_len = mono_metadata_decode_blob_size (named, &named);
7924 name = g_malloc (name_len + 1);
7925 memcpy (name, named, name_len);
7926 name [name_len] = 0;
7928 if (named_type == 0x53) {
7929 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7930 void *val = load_cattr_value (image, field->type, named, &named);
7931 mono_field_set_value (attr, field, val);
7932 if (!type_is_reference (field->type))
7934 } else if (named_type == 0x54) {
7937 MonoType *prop_type;
7939 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7940 /* can we have more that 1 arg in a custom attr named property? */
7941 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7942 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7943 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7944 mono_property_set_value (prop, attr, pparams, NULL);
7945 if (!type_is_reference (prop_type))
7946 g_free (pparams [0]);
7951 if (params != params_buf)
7952 mono_gc_free_fixed (params);
7958 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7960 MonoArray *typedargs, *namedargs;
7961 MonoClass *attrklass;
7962 static MonoMethod *ctor;
7965 const char *p = (const char*)data;
7967 guint32 i, j, num_named;
7970 mono_class_init (method->klass);
7973 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7975 domain = mono_domain_get ();
7977 /* This is for Attributes with no parameters */
7978 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7979 params [0] = mono_method_get_object (domain, method, NULL);
7980 params [1] = params [2] = NULL;
7981 mono_runtime_invoke (method, attr, params, NULL);
7985 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7988 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7992 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7993 MonoObject *obj, *typedarg;
7996 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7997 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7998 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7999 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8000 mono_array_setref (typedargs, i, typedarg);
8002 if (!type_is_reference (mono_method_signature (method)->params [i]))
8007 num_named = read16 (named);
8008 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8010 attrklass = method->klass;
8011 for (j = 0; j < num_named; j++) {
8013 char *name, named_type, data_type;
8014 named_type = *named++;
8015 data_type = *named++; /* type of data */
8016 if (data_type == MONO_TYPE_SZARRAY)
8017 data_type = *named++;
8018 if (data_type == MONO_TYPE_ENUM) {
8021 type_len = mono_metadata_decode_blob_size (named, &named);
8022 type_name = g_malloc (type_len + 1);
8023 memcpy (type_name, named, type_len);
8024 type_name [type_len] = 0;
8026 /* FIXME: lookup the type and check type consistency */
8029 name_len = mono_metadata_decode_blob_size (named, &named);
8030 name = g_malloc (name_len + 1);
8031 memcpy (name, named, name_len);
8032 name [name_len] = 0;
8034 if (named_type == 0x53) {
8035 MonoObject *obj, *typedarg, *namedarg;
8036 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8037 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
8039 minfo = mono_field_get_object (domain, NULL, field);
8040 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8041 typedarg = create_cattr_typed_arg (field->type, obj);
8042 namedarg = create_cattr_named_arg (minfo, typedarg);
8043 mono_array_setref (namedargs, j, namedarg);
8044 if (!type_is_reference (field->type))
8046 } else if (named_type == 0x54) {
8047 MonoObject *obj, *typedarg, *namedarg;
8048 MonoType *prop_type;
8050 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8052 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8053 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8054 minfo = mono_property_get_object (domain, NULL, prop);
8055 val = load_cattr_value (image, prop_type, named, &named);
8056 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8057 typedarg = create_cattr_typed_arg (prop_type, obj);
8058 namedarg = create_cattr_named_arg (minfo, typedarg);
8059 mono_array_setref (namedargs, j, namedarg);
8060 if (!type_is_reference (prop_type))
8065 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8066 params [0] = mono_method_get_object (domain, method, NULL);
8067 params [1] = typedargs;
8068 params [2] = namedargs;
8069 mono_runtime_invoke (ctor, attr, params, NULL);
8074 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8080 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8081 for (i = 0; i < cinfo->num_attrs; ++i) {
8082 if (!cinfo->attrs [i].ctor)
8083 /* The cattr type is not finished yet */
8084 /* We should include the type name but cinfo doesn't contain it */
8085 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8086 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8087 mono_array_setref (result, i, attr);
8093 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8100 for (i = 0; i < cinfo->num_attrs; ++i) {
8101 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8105 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8107 for (i = 0; i < cinfo->num_attrs; ++i) {
8108 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8109 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8110 mono_array_setref (result, n, attr);
8118 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8124 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8125 for (i = 0; i < cinfo->num_attrs; ++i) {
8126 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8127 mono_array_setref (result, i, attr);
8133 * mono_custom_attrs_from_index:
8135 * Returns: NULL if no attributes are found or if a loading error occurs.
8138 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8140 guint32 mtoken, i, len;
8141 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8143 MonoCustomAttrInfo *ainfo;
8144 GList *tmp, *list = NULL;
8147 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8149 i = mono_metadata_custom_attrs_from_index (image, idx);
8153 while (i < ca->rows) {
8154 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8156 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8159 len = g_list_length (list);
8162 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8163 ainfo->num_attrs = len;
8164 ainfo->image = image;
8165 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8166 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8167 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8168 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8169 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8170 mtoken |= MONO_TOKEN_METHOD_DEF;
8172 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8173 mtoken |= MONO_TOKEN_MEMBER_REF;
8176 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8179 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8180 if (!ainfo->attrs [i].ctor) {
8181 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8186 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8187 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8188 ainfo->attrs [i].data = (guchar*)data;
8196 mono_custom_attrs_from_method (MonoMethod *method)
8201 * An instantiated method has the same cattrs as the generic method definition.
8203 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8204 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8206 if (method->is_inflated)
8207 method = ((MonoMethodInflated *) method)->declaring;
8209 if (method->dynamic || method->klass->image->dynamic)
8210 return lookup_custom_attr (method->klass->image, method);
8213 /* Synthetic methods */
8216 idx = mono_method_get_index (method);
8217 idx <<= MONO_CUSTOM_ATTR_BITS;
8218 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8219 return mono_custom_attrs_from_index (method->klass->image, idx);
8223 mono_custom_attrs_from_class (MonoClass *klass)
8227 if (klass->generic_class)
8228 klass = klass->generic_class->container_class;
8230 if (klass->image->dynamic)
8231 return lookup_custom_attr (klass->image, klass);
8233 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8234 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8235 idx <<= MONO_CUSTOM_ATTR_BITS;
8236 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8238 idx = mono_metadata_token_index (klass->type_token);
8239 idx <<= MONO_CUSTOM_ATTR_BITS;
8240 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8242 return mono_custom_attrs_from_index (klass->image, idx);
8246 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8250 if (assembly->image->dynamic)
8251 return lookup_custom_attr (assembly->image, assembly);
8252 idx = 1; /* there is only one assembly */
8253 idx <<= MONO_CUSTOM_ATTR_BITS;
8254 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8255 return mono_custom_attrs_from_index (assembly->image, idx);
8258 static MonoCustomAttrInfo*
8259 mono_custom_attrs_from_module (MonoImage *image)
8264 return lookup_custom_attr (image, image);
8265 idx = 1; /* there is only one module */
8266 idx <<= MONO_CUSTOM_ATTR_BITS;
8267 idx |= MONO_CUSTOM_ATTR_MODULE;
8268 return mono_custom_attrs_from_index (image, idx);
8272 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8276 if (klass->image->dynamic) {
8277 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8278 return lookup_custom_attr (klass->image, property);
8280 idx = find_property_index (klass, property);
8281 idx <<= MONO_CUSTOM_ATTR_BITS;
8282 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8283 return mono_custom_attrs_from_index (klass->image, idx);
8287 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8291 if (klass->image->dynamic) {
8292 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8293 return lookup_custom_attr (klass->image, event);
8295 idx = find_event_index (klass, event);
8296 idx <<= MONO_CUSTOM_ATTR_BITS;
8297 idx |= MONO_CUSTOM_ATTR_EVENT;
8298 return mono_custom_attrs_from_index (klass->image, idx);
8302 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8305 if (klass->image->dynamic) {
8306 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8307 return lookup_custom_attr (klass->image, field);
8309 idx = find_field_index (klass, field);
8310 idx <<= MONO_CUSTOM_ATTR_BITS;
8311 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8312 return mono_custom_attrs_from_index (klass->image, idx);
8316 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8319 guint32 i, idx, method_index;
8320 guint32 param_list, param_last, param_pos, found;
8322 MonoReflectionMethodAux *aux;
8325 * An instantiated method has the same cattrs as the generic method definition.
8327 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8328 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8330 if (method->is_inflated)
8331 method = ((MonoMethodInflated *) method)->declaring;
8333 if (method->klass->image->dynamic) {
8334 MonoCustomAttrInfo *res, *ainfo;
8337 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8338 if (!aux || !aux->param_cattr)
8341 /* Need to copy since it will be freed later */
8342 ainfo = aux->param_cattr [param];
8343 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8344 res = g_malloc0 (size);
8345 memcpy (res, ainfo, size);
8349 image = method->klass->image;
8350 method_index = mono_method_get_index (method);
8351 ca = &image->tables [MONO_TABLE_METHOD];
8353 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8354 if (method_index == ca->rows) {
8355 ca = &image->tables [MONO_TABLE_PARAM];
8356 param_last = ca->rows + 1;
8358 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8359 ca = &image->tables [MONO_TABLE_PARAM];
8362 for (i = param_list; i < param_last; ++i) {
8363 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8364 if (param_pos == param) {
8372 idx <<= MONO_CUSTOM_ATTR_BITS;
8373 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8374 return mono_custom_attrs_from_index (image, idx);
8378 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8382 for (i = 0; i < ainfo->num_attrs; ++i) {
8383 klass = ainfo->attrs [i].ctor->klass;
8384 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8391 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8398 for (i = 0; i < ainfo->num_attrs; ++i) {
8399 klass = ainfo->attrs [i].ctor->klass;
8400 if (mono_class_has_parent (klass, attr_klass)) {
8405 if (attr_index == -1)
8408 attrs = mono_custom_attrs_construct (ainfo);
8410 return mono_array_get (attrs, MonoObject*, attr_index);
8416 * mono_reflection_get_custom_attrs_info:
8417 * @obj: a reflection object handle
8419 * Return the custom attribute info for attributes defined for the
8420 * reflection handle @obj. The objects.
8422 * FIXME this function leaks like a sieve for SRE objects.
8425 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8428 MonoCustomAttrInfo *cinfo = NULL;
8430 klass = obj->vtable->klass;
8431 if (klass == mono_defaults.monotype_class) {
8432 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8433 klass = mono_class_from_mono_type (type);
8434 cinfo = mono_custom_attrs_from_class (klass);
8435 } else if (strcmp ("Assembly", klass->name) == 0) {
8436 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8437 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8438 } else if (strcmp ("Module", klass->name) == 0) {
8439 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8440 cinfo = mono_custom_attrs_from_module (module->image);
8441 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8442 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8443 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8444 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8445 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8446 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8447 } else if (strcmp ("MonoField", klass->name) == 0) {
8448 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8449 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8450 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8451 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8452 cinfo = mono_custom_attrs_from_method (rmethod->method);
8453 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8454 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8455 cinfo = mono_custom_attrs_from_method (rmethod->method);
8456 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8457 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8458 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8459 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8460 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8461 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8462 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8463 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8464 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8465 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8466 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8467 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8468 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8469 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8470 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8471 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8472 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8473 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8474 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8475 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8476 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8477 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8478 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8479 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8480 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8481 } else { /* handle other types here... */
8482 g_error ("get custom attrs not yet supported for %s", klass->name);
8489 * mono_reflection_get_custom_attrs_by_type:
8490 * @obj: a reflection object handle
8492 * Return an array with all the custom attributes defined of the
8493 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8494 * of that type are returned. The objects are fully build. Return NULL if a loading error
8498 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8501 MonoCustomAttrInfo *cinfo;
8503 cinfo = mono_reflection_get_custom_attrs_info (obj);
8506 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8508 result = mono_custom_attrs_construct (cinfo);
8510 mono_custom_attrs_free (cinfo);
8512 if (mono_loader_get_last_error ())
8514 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8521 * mono_reflection_get_custom_attrs:
8522 * @obj: a reflection object handle
8524 * Return an array with all the custom attributes defined of the
8525 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8529 mono_reflection_get_custom_attrs (MonoObject *obj)
8531 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8535 * mono_reflection_get_custom_attrs_data:
8536 * @obj: a reflection obj handle
8538 * Returns an array of System.Reflection.CustomAttributeData,
8539 * which include information about attributes reflected on
8540 * types loaded using the Reflection Only methods
8543 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8546 MonoCustomAttrInfo *cinfo;
8548 cinfo = mono_reflection_get_custom_attrs_info (obj);
8550 result = mono_custom_attrs_data_construct (cinfo);
8552 mono_custom_attrs_free (cinfo);
8554 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8559 static MonoReflectionType*
8560 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8562 MonoMethod *method_get_underlying_system_type;
8564 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8565 mono_class_get_method_from_name (mono_object_class (t),
8566 "get_UnderlyingSystemType",
8568 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8571 #ifndef DISABLE_REFLECTION_EMIT
8574 is_corlib_type (MonoClass *class)
8576 return class->image == mono_defaults.corlib;
8580 is_usertype (MonoReflectionType *ref)
8582 MonoClass *class = mono_object_class (ref);
8583 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8586 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8587 static MonoClass *cached_class; \
8589 return cached_class == _class; \
8590 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8591 cached_class = _class; \
8598 is_sre_array (MonoClass *class)
8600 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8604 is_sre_byref (MonoClass *class)
8606 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8610 is_sre_pointer (MonoClass *class)
8612 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8616 is_sre_generic_instance (MonoClass *class)
8618 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8622 mono_reflection_type_get_handle (MonoReflectionType* ref)
8630 if (is_usertype (ref)) {
8631 ref = mono_reflection_type_get_underlying_system_type (ref);
8632 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8637 class = mono_object_class (ref);
8639 if (is_sre_array (class)) {
8641 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8642 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8644 if (sre_array->rank == 0) //single dimentional array
8645 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8647 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8648 sre_array->type.type = res;
8650 } else if (is_sre_byref (class)) {
8652 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8653 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8655 res = &mono_class_from_mono_type (base)->this_arg;
8656 sre_byref->type.type = res;
8658 } else if (is_sre_pointer (class)) {
8660 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8661 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8663 res = &mono_ptr_class_get (base)->byval_arg;
8664 sre_pointer->type.type = res;
8666 } else if (is_sre_generic_instance (class)) {
8667 MonoType *res, **types;
8668 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8671 count = mono_array_length (gclass->type_arguments);
8672 types = g_new0 (MonoType*, count);
8673 for (i = 0; i < count; ++i) {
8674 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8675 types [i] = mono_reflection_type_get_handle (t);
8678 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8681 gclass->type.type = res;
8685 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8689 static MonoReflectionType*
8690 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8692 if (!type || type->type)
8695 if (is_usertype (type)) {
8696 type = mono_reflection_type_get_underlying_system_type (type);
8697 if (is_usertype (type))
8698 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8705 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8707 mono_reflection_type_get_handle (type);
8711 * LOCKING: Assumes the loader lock is held.
8713 static MonoMethodSignature*
8714 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8715 MonoMethodSignature *sig;
8718 count = parameters? mono_array_length (parameters): 0;
8720 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8721 sig->param_count = count;
8722 sig->sentinelpos = -1; /* FIXME */
8723 for (i = 0; i < count; ++i)
8724 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8729 * LOCKING: Assumes the loader lock is held.
8731 static MonoMethodSignature*
8732 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8733 MonoMethodSignature *sig;
8735 sig = parameters_to_signature (image, ctor->parameters);
8736 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8737 sig->ret = &mono_defaults.void_class->byval_arg;
8742 * LOCKING: Assumes the loader lock is held.
8744 static MonoMethodSignature*
8745 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8746 MonoMethodSignature *sig;
8748 sig = parameters_to_signature (image, method->parameters);
8749 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8750 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8751 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8755 static MonoMethodSignature*
8756 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8757 MonoMethodSignature *sig;
8759 sig = parameters_to_signature (NULL, method->parameters);
8760 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8761 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8762 sig->generic_param_count = 0;
8767 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8769 MonoClass *klass = mono_object_class (prop);
8770 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8771 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8772 *name = mono_string_to_utf8 (pb->name);
8773 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8775 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8776 *name = g_strdup (p->property->name);
8777 if (p->property->get)
8778 *type = mono_method_signature (p->property->get)->ret;
8780 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8785 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8787 MonoClass *klass = mono_object_class (field);
8788 if (strcmp (klass->name, "FieldBuilder") == 0) {
8789 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8790 *name = mono_string_to_utf8 (fb->name);
8791 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8793 MonoReflectionField *f = (MonoReflectionField *)field;
8794 *name = g_strdup (mono_field_get_name (f->field));
8795 *type = f->field->type;
8798 #endif /* !DISABLE_REFLECTION_EMIT */
8801 * Encode a value in a custom attribute stream of bytes.
8802 * The value to encode is either supplied as an object in argument val
8803 * (valuetypes are boxed), or as a pointer to the data in the
8805 * @type represents the type of the value
8806 * @buffer is the start of the buffer
8807 * @p the current position in the buffer
8808 * @buflen contains the size of the buffer and is used to return the new buffer size
8809 * if this needs to be realloced.
8810 * @retbuffer and @retp return the start and the position of the buffer
8813 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8815 MonoTypeEnum simple_type;
8817 if ((p-buffer) + 10 >= *buflen) {
8820 newbuf = g_realloc (buffer, *buflen);
8821 p = newbuf + (p-buffer);
8825 argval = ((char*)arg + sizeof (MonoObject));
8826 simple_type = type->type;
8828 switch (simple_type) {
8829 case MONO_TYPE_BOOLEAN:
8834 case MONO_TYPE_CHAR:
8837 swap_with_size (p, argval, 2, 1);
8843 swap_with_size (p, argval, 4, 1);
8847 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8857 swap_with_size (p, argval, 8, 1);
8863 swap_with_size (p, argval, 8, 1);
8866 case MONO_TYPE_VALUETYPE:
8867 if (type->data.klass->enumtype) {
8868 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8871 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8874 case MONO_TYPE_STRING: {
8881 str = mono_string_to_utf8 ((MonoString*)arg);
8882 slen = strlen (str);
8883 if ((p-buffer) + 10 + slen >= *buflen) {
8887 newbuf = g_realloc (buffer, *buflen);
8888 p = newbuf + (p-buffer);
8891 mono_metadata_encode_value (slen, p, &p);
8892 memcpy (p, str, slen);
8897 case MONO_TYPE_CLASS: {
8905 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8906 slen = strlen (str);
8907 if ((p-buffer) + 10 + slen >= *buflen) {
8911 newbuf = g_realloc (buffer, *buflen);
8912 p = newbuf + (p-buffer);
8915 mono_metadata_encode_value (slen, p, &p);
8916 memcpy (p, str, slen);
8921 case MONO_TYPE_SZARRAY: {
8923 MonoClass *eclass, *arg_eclass;
8926 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8929 len = mono_array_length ((MonoArray*)arg);
8931 *p++ = (len >> 8) & 0xff;
8932 *p++ = (len >> 16) & 0xff;
8933 *p++ = (len >> 24) & 0xff;
8935 *retbuffer = buffer;
8936 eclass = type->data.klass;
8937 arg_eclass = mono_object_class (arg)->element_class;
8940 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8941 eclass = mono_defaults.object_class;
8943 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8944 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8945 int elsize = mono_class_array_element_size (arg_eclass);
8946 for (i = 0; i < len; ++i) {
8947 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8950 } else if (eclass->valuetype && arg_eclass->valuetype) {
8951 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8952 int elsize = mono_class_array_element_size (eclass);
8953 for (i = 0; i < len; ++i) {
8954 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8958 for (i = 0; i < len; ++i) {
8959 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8964 case MONO_TYPE_OBJECT: {
8970 * The parameter type is 'object' but the type of the actual
8971 * argument is not. So we have to add type information to the blob
8972 * too. This is completely undocumented in the spec.
8976 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8981 klass = mono_object_class (arg);
8983 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8986 } else if (klass->enumtype) {
8988 } else if (klass == mono_defaults.string_class) {
8989 simple_type = MONO_TYPE_STRING;
8992 } else if (klass->rank == 1) {
8994 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8995 /* See Partition II, Appendix B3 */
8998 *p++ = klass->element_class->byval_arg.type;
8999 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9001 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9002 *p++ = simple_type = klass->byval_arg.type;
9005 g_error ("unhandled type in custom attr");
9007 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9008 slen = strlen (str);
9009 if ((p-buffer) + 10 + slen >= *buflen) {
9013 newbuf = g_realloc (buffer, *buflen);
9014 p = newbuf + (p-buffer);
9017 mono_metadata_encode_value (slen, p, &p);
9018 memcpy (p, str, slen);
9021 simple_type = mono_class_enum_basetype (klass)->type;
9025 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9028 *retbuffer = buffer;
9032 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9034 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9035 char *str = type_get_qualified_name (type, NULL);
9036 int slen = strlen (str);
9040 * This seems to be optional...
9043 mono_metadata_encode_value (slen, p, &p);
9044 memcpy (p, str, slen);
9047 } else if (type->type == MONO_TYPE_OBJECT) {
9049 } else if (type->type == MONO_TYPE_CLASS) {
9050 /* it should be a type: encode_cattr_value () has the check */
9053 mono_metadata_encode_value (type->type, p, &p);
9054 if (type->type == MONO_TYPE_SZARRAY)
9055 /* See the examples in Partition VI, Annex B */
9056 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9062 #ifndef DISABLE_REFLECTION_EMIT
9064 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9067 /* Preallocate a large enough buffer */
9068 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9069 char *str = type_get_qualified_name (type, NULL);
9072 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9073 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9079 len += strlen (name);
9081 if ((p-buffer) + 20 + len >= *buflen) {
9085 newbuf = g_realloc (buffer, *buflen);
9086 p = newbuf + (p-buffer);
9090 encode_field_or_prop_type (type, p, &p);
9092 len = strlen (name);
9093 mono_metadata_encode_value (len, p, &p);
9094 memcpy (p, name, len);
9096 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9098 *retbuffer = buffer;
9102 * mono_reflection_get_custom_attrs_blob:
9103 * @ctor: custom attribute constructor
9104 * @ctorArgs: arguments o the constructor
9110 * Creates the blob of data that needs to be saved in the metadata and that represents
9111 * the custom attributed described by @ctor, @ctorArgs etc.
9112 * Returns: a Byte array representing the blob of data.
9115 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9118 MonoMethodSignature *sig;
9123 MONO_ARCH_SAVE_REGS;
9125 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9126 /* sig is freed later so allocate it in the heap */
9127 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9129 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9132 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9134 p = buffer = g_malloc (buflen);
9135 /* write the prolog */
9138 for (i = 0; i < sig->param_count; ++i) {
9139 arg = mono_array_get (ctorArgs, MonoObject*, i);
9140 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9144 i += mono_array_length (properties);
9146 i += mono_array_length (fields);
9148 *p++ = (i >> 8) & 0xff;
9151 for (i = 0; i < mono_array_length (properties); ++i) {
9155 prop = mono_array_get (properties, gpointer, i);
9156 get_prop_name_and_type (prop, &pname, &ptype);
9157 *p++ = 0x54; /* PROPERTY signature */
9158 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9165 for (i = 0; i < mono_array_length (fields); ++i) {
9169 field = mono_array_get (fields, gpointer, i);
9170 get_field_name_and_type (field, &fname, &ftype);
9171 *p++ = 0x53; /* FIELD signature */
9172 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9177 g_assert (p - buffer <= buflen);
9178 buflen = p - buffer;
9179 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9180 p = mono_array_addr (result, char, 0);
9181 memcpy (p, buffer, buflen);
9183 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9189 * mono_reflection_setup_internal_class:
9190 * @tb: a TypeBuilder object
9192 * Creates a MonoClass that represents the TypeBuilder.
9193 * This is a trick that lets us simplify a lot of reflection code
9194 * (and will allow us to support Build and Run assemblies easier).
9197 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9199 MonoClass *klass, *parent;
9201 MONO_ARCH_SAVE_REGS;
9203 RESOLVE_TYPE (tb->parent);
9205 mono_loader_lock ();
9208 /* check so we can compile corlib correctly */
9209 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9210 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9211 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9213 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9219 /* the type has already being created: it means we just have to change the parent */
9220 if (tb->type.type) {
9221 klass = mono_class_from_mono_type (tb->type.type);
9222 klass->parent = NULL;
9223 /* fool mono_class_setup_parent */
9224 klass->supertypes = NULL;
9225 mono_class_setup_parent (klass, parent);
9226 mono_class_setup_mono_type (klass);
9227 mono_loader_unlock ();
9231 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9233 klass->image = &tb->module->dynamic_image->image;
9235 klass->inited = 1; /* we lie to the runtime */
9236 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9237 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9238 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9239 klass->flags = tb->attrs;
9241 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9243 klass->element_class = klass;
9245 MOVING_GC_REGISTER (&klass->reflection_info);
9246 klass->reflection_info = tb;
9248 /* Put into cache so mono_class_get () will find it */
9249 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9251 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9252 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9254 if (parent != NULL) {
9255 mono_class_setup_parent (klass, parent);
9256 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9257 const char *old_n = klass->name;
9258 /* trick to get relative numbering right when compiling corlib */
9259 klass->name = "BuildingObject";
9260 mono_class_setup_parent (klass, mono_defaults.object_class);
9261 klass->name = old_n;
9264 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9265 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9266 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9267 klass->instance_size = sizeof (MonoObject);
9268 klass->size_inited = 1;
9269 mono_class_setup_vtable_general (klass, NULL, 0);
9272 mono_class_setup_mono_type (klass);
9274 mono_class_setup_supertypes (klass);
9277 * FIXME: handle interfaces.
9280 tb->type.type = &klass->byval_arg;
9282 if (tb->nesting_type) {
9283 g_assert (tb->nesting_type->type);
9284 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9287 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9289 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9291 mono_loader_unlock ();
9295 * mono_reflection_setup_generic_class:
9296 * @tb: a TypeBuilder object
9298 * Setup the generic class before adding the first generic parameter.
9301 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9306 * mono_reflection_create_generic_class:
9307 * @tb: a TypeBuilder object
9309 * Creates the generic class after all generic parameters have been added.
9312 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9317 MONO_ARCH_SAVE_REGS;
9319 klass = mono_class_from_mono_type (tb->type.type);
9321 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9323 if (klass->generic_container || (count == 0))
9326 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9328 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9330 klass->generic_container->owner.klass = klass;
9331 klass->generic_container->type_argc = count;
9332 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9334 klass->is_generic = 1;
9336 for (i = 0; i < count; i++) {
9337 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9338 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9339 klass->generic_container->type_params [i] = *param;
9340 /*Make sure we are a diferent type instance */
9341 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9342 klass->generic_container->type_params [i].info.pklass = NULL;
9344 g_assert (klass->generic_container->type_params [i].param.owner);
9347 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9351 * mono_reflection_create_internal_class:
9352 * @tb: a TypeBuilder object
9354 * Actually create the MonoClass that is associated with the TypeBuilder.
9357 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9361 MONO_ARCH_SAVE_REGS;
9363 klass = mono_class_from_mono_type (tb->type.type);
9365 mono_loader_lock ();
9366 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9367 MonoReflectionFieldBuilder *fb;
9369 MonoType *enum_basetype;
9371 g_assert (tb->fields != NULL);
9372 g_assert (mono_array_length (tb->fields) >= 1);
9374 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9376 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9377 mono_loader_unlock ();
9381 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9382 klass->element_class = mono_class_from_mono_type (enum_basetype);
9383 if (!klass->element_class)
9384 klass->element_class = mono_class_from_mono_type (enum_basetype);
9387 * get the element_class from the current corlib.
9389 ec = default_class_from_mono_type (enum_basetype);
9390 klass->instance_size = ec->instance_size;
9391 klass->size_inited = 1;
9393 * this is almost safe to do with enums and it's needed to be able
9394 * to create objects of the enum type (for use in SetConstant).
9396 /* FIXME: Does this mean enums can't have method overrides ? */
9397 mono_class_setup_vtable_general (klass, NULL, 0);
9399 mono_loader_unlock ();
9402 static MonoMarshalSpec*
9403 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9404 MonoReflectionMarshal *minfo)
9406 MonoMarshalSpec *res;
9408 res = image_g_new0 (image, MonoMarshalSpec, 1);
9409 res->native = minfo->type;
9411 switch (minfo->type) {
9412 case MONO_NATIVE_LPARRAY:
9413 res->data.array_data.elem_type = minfo->eltype;
9414 if (minfo->has_size) {
9415 res->data.array_data.param_num = minfo->param_num;
9416 res->data.array_data.num_elem = minfo->count;
9417 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9420 res->data.array_data.param_num = -1;
9421 res->data.array_data.num_elem = -1;
9422 res->data.array_data.elem_mult = -1;
9426 case MONO_NATIVE_BYVALTSTR:
9427 case MONO_NATIVE_BYVALARRAY:
9428 res->data.array_data.num_elem = minfo->count;
9431 case MONO_NATIVE_CUSTOM:
9432 if (minfo->marshaltyperef)
9433 res->data.custom_data.custom_name =
9434 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9436 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9445 #endif /* !DISABLE_REFLECTION_EMIT */
9447 MonoReflectionMarshal*
9448 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9449 MonoMarshalSpec *spec)
9451 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9452 MonoReflectionMarshal *minfo;
9455 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9456 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9457 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9458 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9461 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9462 minfo->type = spec->native;
9464 switch (minfo->type) {
9465 case MONO_NATIVE_LPARRAY:
9466 minfo->eltype = spec->data.array_data.elem_type;
9467 minfo->count = spec->data.array_data.num_elem;
9468 minfo->param_num = spec->data.array_data.param_num;
9471 case MONO_NATIVE_BYVALTSTR:
9472 case MONO_NATIVE_BYVALARRAY:
9473 minfo->count = spec->data.array_data.num_elem;
9476 case MONO_NATIVE_CUSTOM:
9477 if (spec->data.custom_data.custom_name) {
9478 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9480 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9482 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9484 if (spec->data.custom_data.cookie)
9485 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9495 #ifndef DISABLE_REFLECTION_EMIT
9497 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9498 ReflectionMethodBuilder *rmb,
9499 MonoMethodSignature *sig)
9502 MonoMethodNormal *pm;
9503 MonoMarshalSpec **specs;
9504 MonoReflectionMethodAux *method_aux;
9510 * Methods created using a MethodBuilder should have their memory allocated
9511 * inside the image mempool, while dynamic methods should have their memory
9514 dynamic = rmb->refs != NULL;
9515 image = dynamic ? NULL : klass->image;
9518 g_assert (!klass->generic_class);
9520 mono_loader_lock ();
9522 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9523 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9524 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9526 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9528 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9530 pm = (MonoMethodNormal*)m;
9532 m->dynamic = dynamic;
9534 m->flags = rmb->attrs;
9535 m->iflags = rmb->iattrs;
9536 m->name = mono_string_to_utf8_image (image, rmb->name);
9539 m->skip_visibility = rmb->skip_visibility;
9541 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9543 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9544 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9547 m->signature->pinvoke = 1;
9548 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9549 m->signature->pinvoke = 1;
9551 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9553 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9554 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9556 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9558 if (klass->image->dynamic)
9559 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9561 mono_loader_unlock ();
9564 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9565 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9566 MonoMethodHeader *header;
9568 gint32 max_stack, i;
9569 gint32 num_locals = 0;
9570 gint32 num_clauses = 0;
9574 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9575 code_size = rmb->ilgen->code_len;
9576 max_stack = rmb->ilgen->max_stack;
9577 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9578 if (rmb->ilgen->ex_handlers)
9579 num_clauses = method_count_clauses (rmb->ilgen);
9582 code = mono_array_addr (rmb->code, guint8, 0);
9583 code_size = mono_array_length (rmb->code);
9584 /* we probably need to run a verifier on the code... */
9594 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9595 header->code_size = code_size;
9596 header->code = image_g_malloc (image, code_size);
9597 memcpy ((char*)header->code, code, code_size);
9598 header->max_stack = max_stack;
9599 header->init_locals = rmb->init_locals;
9600 header->num_locals = num_locals;
9602 for (i = 0; i < num_locals; ++i) {
9603 MonoReflectionLocalBuilder *lb =
9604 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9606 header->locals [i] = image_g_new0 (image, MonoType, 1);
9607 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9610 header->num_clauses = num_clauses;
9612 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9613 rmb->ilgen, num_clauses);
9616 pm->header = header;
9619 if (rmb->generic_params) {
9620 int count = mono_array_length (rmb->generic_params);
9621 MonoGenericContainer *container;
9623 container = rmb->generic_container;
9625 m->is_generic = TRUE;
9626 mono_method_set_generic_container (m, container);
9628 container->type_argc = count;
9629 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9630 container->owner.method = m;
9632 for (i = 0; i < count; i++) {
9633 MonoReflectionGenericParam *gp =
9634 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9635 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9636 container->type_params [i] = *param;
9639 if (klass->generic_container) {
9640 container->parent = klass->generic_container;
9641 container->context.class_inst = klass->generic_container->context.class_inst;
9643 container->context.method_inst = mono_get_shared_generic_inst (container);
9647 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9651 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9653 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9654 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9655 for (i = 0; i < rmb->nrefs; ++i)
9656 data [i + 1] = rmb->refs [i];
9661 /* Parameter info */
9664 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9665 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9666 for (i = 0; i <= m->signature->param_count; ++i) {
9667 MonoReflectionParamBuilder *pb;
9668 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9669 if ((i > 0) && (pb->attrs)) {
9670 /* Make a copy since it might point to a shared type structure */
9671 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9672 m->signature->params [i - 1]->attrs = pb->attrs;
9675 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9676 MonoDynamicImage *assembly;
9677 guint32 idx, def_type, len;
9681 if (!method_aux->param_defaults) {
9682 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9683 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9685 assembly = (MonoDynamicImage*)klass->image;
9686 idx = encode_constant (assembly, pb->def_value, &def_type);
9687 /* Copy the data from the blob since it might get realloc-ed */
9688 p = assembly->blob.data + idx;
9689 len = mono_metadata_decode_blob_size (p, &p2);
9691 method_aux->param_defaults [i] = image_g_malloc (image, len);
9692 method_aux->param_default_types [i] = def_type;
9693 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9697 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9699 if (!method_aux->param_cattr)
9700 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9701 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9707 /* Parameter marshalling */
9710 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9711 MonoReflectionParamBuilder *pb;
9712 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9713 if (pb->marshal_info) {
9715 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9716 specs [pb->position] =
9717 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9721 if (specs != NULL) {
9723 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9724 method_aux->param_marshall = specs;
9727 if (klass->image->dynamic && method_aux)
9728 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9730 mono_loader_unlock ();
9736 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9738 ReflectionMethodBuilder rmb;
9739 MonoMethodSignature *sig;
9741 mono_loader_lock ();
9742 sig = ctor_builder_to_signature (klass->image, mb);
9743 mono_loader_unlock ();
9745 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9747 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9748 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9750 /* If we are in a generic class, we might be called multiple times from inflate_method */
9751 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9752 /* ilgen is no longer needed */
9760 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9762 ReflectionMethodBuilder rmb;
9763 MonoMethodSignature *sig;
9765 mono_loader_lock ();
9766 sig = method_builder_to_signature (klass->image, mb);
9767 mono_loader_unlock ();
9769 reflection_methodbuilder_from_method_builder (&rmb, mb);
9771 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9772 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9774 /* If we are in a generic class, we might be called multiple times from inflate_method */
9775 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9776 /* ilgen is no longer needed */
9782 static MonoClassField*
9783 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9785 MonoClassField *field;
9788 field = g_new0 (MonoClassField, 1);
9790 field->name = mono_string_to_utf8 (fb->name);
9791 if (fb->attrs || fb->modreq || fb->modopt) {
9792 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9793 field->type->attrs = fb->attrs;
9795 g_assert (klass->image->dynamic);
9796 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9797 g_free (field->type);
9798 field->type = custom;
9800 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9802 if (fb->offset != -1)
9803 field->offset = fb->offset;
9804 field->parent = klass;
9805 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9807 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9814 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9817 MonoReflectionTypeBuilder *tb = NULL;
9818 gboolean is_dynamic = FALSE;
9822 mono_loader_lock ();
9824 domain = mono_object_domain (type);
9826 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9827 tb = (MonoReflectionTypeBuilder *) type;
9830 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9831 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9833 tb = rgi->generic_type;
9837 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9838 if (tb && tb->generic_container)
9839 mono_reflection_create_generic_class (tb);
9841 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9842 if (!klass->generic_container) {
9843 mono_loader_unlock ();
9847 if (klass->wastypebuilder) {
9848 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9853 mono_loader_unlock ();
9855 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9857 return &geninst->byval_arg;
9861 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9863 MonoGenericClass *gclass;
9864 MonoGenericInst *inst;
9866 g_assert (klass->generic_container);
9868 inst = mono_metadata_get_generic_inst (type_argc, types);
9869 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9871 return mono_generic_class_get_class (gclass);
9874 MonoReflectionMethod*
9875 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9878 MonoMethod *method, *inflated;
9879 MonoMethodInflated *imethod;
9880 MonoGenericContext tmp_context;
9881 MonoGenericInst *ginst;
9882 MonoType **type_argv;
9885 MONO_ARCH_SAVE_REGS;
9887 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9888 #ifndef DISABLE_REFLECTION_EMIT
9889 MonoReflectionMethodBuilder *mb = NULL;
9890 MonoReflectionTypeBuilder *tb;
9893 mb = (MonoReflectionMethodBuilder *) rmethod;
9894 tb = (MonoReflectionTypeBuilder *) mb->type;
9895 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9897 method = methodbuilder_to_mono_method (klass, mb);
9899 g_assert_not_reached ();
9903 method = rmethod->method;
9906 klass = method->klass;
9908 if (method->is_inflated)
9909 method = ((MonoMethodInflated *) method)->declaring;
9911 count = mono_method_signature (method)->generic_param_count;
9912 if (count != mono_array_length (types))
9915 type_argv = g_new0 (MonoType *, count);
9916 for (i = 0; i < count; i++) {
9917 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9918 type_argv [i] = mono_reflection_type_get_handle (garg);
9920 ginst = mono_metadata_get_generic_inst (count, type_argv);
9923 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9924 tmp_context.method_inst = ginst;
9926 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9927 imethod = (MonoMethodInflated *) inflated;
9929 if (method->klass->image->dynamic) {
9930 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9932 * This table maps metadata structures representing inflated methods/fields
9933 * to the reflection objects representing their generic definitions.
9935 mono_loader_lock ();
9936 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9937 mono_loader_unlock ();
9940 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9943 #ifndef DISABLE_REFLECTION_EMIT
9946 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9948 MonoMethodInflated *imethod;
9949 MonoGenericContext *context;
9953 * With generic code sharing the klass might not be inflated.
9954 * This can happen because classes inflated with their own
9955 * type arguments are "normalized" to the uninflated class.
9957 if (!klass->generic_class)
9960 context = mono_class_get_context (klass);
9962 if (klass->method.count) {
9963 /* Find the already created inflated method */
9964 for (i = 0; i < klass->method.count; ++i) {
9965 g_assert (klass->methods [i]->is_inflated);
9966 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9969 g_assert (i < klass->method.count);
9970 imethod = (MonoMethodInflated*)klass->methods [i];
9972 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9975 if (method->is_generic && method->klass->image->dynamic) {
9976 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9978 mono_loader_lock ();
9979 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9980 mono_loader_unlock ();
9982 return (MonoMethod *) imethod;
9986 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9991 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
9993 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9994 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9995 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9997 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9998 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9999 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10000 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10001 method = ((MonoReflectionMethod *) obj)->method;
10003 method = NULL; /* prevent compiler warning */
10004 g_error ("can't handle type %s", obj->vtable->klass->name);
10007 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10010 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10012 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10013 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10016 MonoGenericClass *gclass;
10017 MonoDynamicGenericClass *dgclass;
10018 MonoClass *klass, *gklass;
10022 MONO_ARCH_SAVE_REGS;
10024 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10025 klass = mono_class_from_mono_type (gtype);
10026 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10027 gclass = gtype->data.generic_class;
10029 g_assert (gclass->is_dynamic);
10030 dgclass = (MonoDynamicGenericClass *) gclass;
10032 if (dgclass->initialized)
10035 gklass = gclass->container_class;
10036 mono_class_init (gklass);
10038 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10039 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10040 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10041 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10042 dgclass->count_events = events ? mono_array_length (events) : 0;
10044 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10045 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10046 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10047 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10048 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10049 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10050 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10052 for (i = 0; i < dgclass->count_methods; i++) {
10053 MonoObject *obj = mono_array_get (methods, gpointer, i);
10055 dgclass->methods [i] = inflate_method (type, obj);
10058 for (i = 0; i < dgclass->count_ctors; i++) {
10059 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10061 dgclass->ctors [i] = inflate_method (type, obj);
10064 for (i = 0; i < dgclass->count_fields; i++) {
10065 MonoObject *obj = mono_array_get (fields, gpointer, i);
10066 MonoClassField *field, *inflated_field = NULL;
10068 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10069 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10070 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10071 field = ((MonoReflectionField *) obj)->field;
10073 field = NULL; /* prevent compiler warning */
10074 g_assert_not_reached ();
10077 dgclass->fields [i] = *field;
10078 dgclass->fields [i].parent = klass;
10079 dgclass->fields [i].type = mono_class_inflate_generic_type (
10080 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10081 dgclass->field_generic_types [i] = field->type;
10082 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10083 dgclass->field_objects [i] = obj;
10085 if (inflated_field) {
10086 g_free (inflated_field);
10088 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10092 for (i = 0; i < dgclass->count_properties; i++) {
10093 MonoObject *obj = mono_array_get (properties, gpointer, i);
10094 MonoProperty *property = &dgclass->properties [i];
10096 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10097 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10099 property->parent = klass;
10100 property->attrs = pb->attrs;
10101 property->name = mono_string_to_utf8 (pb->name);
10102 if (pb->get_method)
10103 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10104 if (pb->set_method)
10105 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10106 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10107 *property = *((MonoReflectionProperty *) obj)->property;
10108 property->name = g_strdup (property->name);
10111 property->get = inflate_mono_method (klass, property->get, NULL);
10113 property->set = inflate_mono_method (klass, property->set, NULL);
10115 g_assert_not_reached ();
10118 for (i = 0; i < dgclass->count_events; i++) {
10119 MonoObject *obj = mono_array_get (events, gpointer, i);
10120 MonoEvent *event = &dgclass->events [i];
10122 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10123 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10125 event->parent = klass;
10126 event->attrs = eb->attrs;
10127 event->name = mono_string_to_utf8 (eb->name);
10128 if (eb->add_method)
10129 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10130 if (eb->remove_method)
10131 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10132 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10133 *event = *((MonoReflectionMonoEvent *) obj)->event;
10134 event->name = g_strdup (event->name);
10137 event->add = inflate_mono_method (klass, event->add, NULL);
10139 event->remove = inflate_mono_method (klass, event->remove, NULL);
10141 g_assert_not_reached ();
10144 dgclass->initialized = TRUE;
10148 ensure_generic_class_runtime_vtable (MonoClass *klass)
10150 MonoClass *gklass = klass->generic_class->container_class;
10153 if (klass->wastypebuilder)
10156 ensure_runtime_vtable (gklass);
10158 klass->method.count = gklass->method.count;
10159 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10161 for (i = 0; i < klass->method.count; i++) {
10162 klass->methods [i] = mono_class_inflate_generic_method_full (
10163 gklass->methods [i], klass, mono_class_get_context (klass));
10166 klass->interface_count = gklass->interface_count;
10167 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10168 for (i = 0; i < klass->interface_count; ++i) {
10169 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10170 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10171 mono_metadata_free_type (iface_type);
10173 ensure_runtime_vtable (klass->interfaces [i]);
10175 klass->interfaces_inited = 1;
10177 /*We can only finish with this klass once it's parent has as well*/
10178 if (gklass->wastypebuilder)
10179 klass->wastypebuilder = TRUE;
10184 ensure_runtime_vtable (MonoClass *klass)
10186 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10189 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10192 ensure_runtime_vtable (klass->parent);
10195 num = tb->ctors? mono_array_length (tb->ctors): 0;
10196 num += tb->num_methods;
10197 klass->method.count = num;
10198 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10199 num = tb->ctors? mono_array_length (tb->ctors): 0;
10200 for (i = 0; i < num; ++i)
10201 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10202 num = tb->num_methods;
10204 for (i = 0; i < num; ++i)
10205 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10207 if (tb->interfaces) {
10208 klass->interface_count = mono_array_length (tb->interfaces);
10209 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10210 for (i = 0; i < klass->interface_count; ++i) {
10211 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10212 klass->interfaces [i] = mono_class_from_mono_type (iface);
10213 ensure_runtime_vtable (klass->interfaces [i]);
10215 klass->interfaces_inited = 1;
10217 } else if (klass->generic_class){
10218 ensure_generic_class_runtime_vtable (klass);
10221 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10222 for (i = 0; i < klass->method.count; ++i)
10223 klass->methods [i]->slot = i;
10225 mono_class_setup_interface_offsets (klass);
10226 mono_class_setup_interface_id (klass);
10230 * The generic vtable is needed even if image->run is not set since some
10231 * runtime code like ves_icall_Type_GetMethodsByName depends on
10232 * method->slot being defined.
10236 * tb->methods could not be freed since it is used for determining
10237 * overrides during dynamic vtable construction.
10242 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10244 MonoReflectionTypeBuilder *tb;
10248 *num_overrides = 0;
10250 g_assert (klass->image->dynamic);
10252 if (!klass->reflection_info)
10255 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10257 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10261 for (i = 0; i < tb->num_methods; ++i) {
10262 MonoReflectionMethodBuilder *mb =
10263 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10264 if (mb->override_method)
10270 *overrides = g_new0 (MonoMethod*, onum * 2);
10273 for (i = 0; i < tb->num_methods; ++i) {
10274 MonoReflectionMethodBuilder *mb =
10275 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10276 if (mb->override_method) {
10277 (*overrides) [onum * 2] =
10278 mb->override_method->method;
10279 (*overrides) [onum * 2 + 1] =
10282 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10283 g_assert (mb->override_method->method);
10284 g_assert (mb->mhandle);
10291 *num_overrides = onum;
10295 typebuilder_setup_fields (MonoClass *klass)
10297 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10298 MonoReflectionFieldBuilder *fb;
10299 MonoClassField *field;
10300 MonoImage *image = klass->image;
10301 const char *p, *p2;
10303 guint32 len, idx, real_size = 0;
10305 klass->field.count = tb->num_fields;
10306 klass->field.first = 0;
10308 if (tb->class_size) {
10309 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10310 klass->packing_size = tb->packing_size;
10311 real_size = klass->instance_size + tb->class_size;
10314 if (!klass->field.count) {
10315 klass->instance_size = MAX (klass->instance_size, real_size);
10319 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10320 mono_class_alloc_ext (klass);
10321 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10323 for (i = 0; i < klass->field.count; ++i) {
10324 fb = mono_array_get (tb->fields, gpointer, i);
10325 field = &klass->fields [i];
10326 field->name = mono_string_to_utf8_image (image, fb->name);
10328 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10329 field->type->attrs = fb->attrs;
10331 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10333 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10334 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10335 if (fb->offset != -1)
10336 field->offset = fb->offset;
10337 field->parent = klass;
10338 fb->handle = field;
10339 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10341 if (fb->def_value) {
10342 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10343 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10344 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10345 /* Copy the data from the blob since it might get realloc-ed */
10346 p = assembly->blob.data + idx;
10347 len = mono_metadata_decode_blob_size (p, &p2);
10349 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10350 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10354 klass->instance_size = MAX (klass->instance_size, real_size);
10355 mono_class_layout_fields (klass);
10359 typebuilder_setup_properties (MonoClass *klass)
10361 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10362 MonoReflectionPropertyBuilder *pb;
10363 MonoImage *image = klass->image;
10364 MonoProperty *properties;
10368 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10370 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10371 klass->ext->property.first = 0;
10373 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10374 klass->ext->properties = properties;
10375 for (i = 0; i < klass->ext->property.count; ++i) {
10376 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10377 properties [i].parent = klass;
10378 properties [i].attrs = pb->attrs;
10379 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10380 if (pb->get_method)
10381 properties [i].get = pb->get_method->mhandle;
10382 if (pb->set_method)
10383 properties [i].set = pb->set_method->mhandle;
10385 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10389 MonoReflectionEvent *
10390 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10392 MonoEvent *event = g_new0 (MonoEvent, 1);
10396 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10398 event->parent = klass;
10399 event->attrs = eb->attrs;
10400 event->name = mono_string_to_utf8 (eb->name);
10401 if (eb->add_method)
10402 event->add = eb->add_method->mhandle;
10403 if (eb->remove_method)
10404 event->remove = eb->remove_method->mhandle;
10405 if (eb->raise_method)
10406 event->raise = eb->raise_method->mhandle;
10408 if (eb->other_methods) {
10409 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10410 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10411 MonoReflectionMethodBuilder *mb =
10412 mono_array_get (eb->other_methods,
10413 MonoReflectionMethodBuilder*, j);
10414 event->other [j] = mb->mhandle;
10418 return mono_event_get_object (mono_object_domain (tb), klass, event);
10422 typebuilder_setup_events (MonoClass *klass)
10424 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10425 MonoReflectionEventBuilder *eb;
10426 MonoImage *image = klass->image;
10431 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10433 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10434 klass->ext->event.first = 0;
10436 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10437 klass->ext->events = events;
10438 for (i = 0; i < klass->ext->event.count; ++i) {
10439 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10440 events [i].parent = klass;
10441 events [i].attrs = eb->attrs;
10442 events [i].name = mono_string_to_utf8_image (image, eb->name);
10443 if (eb->add_method)
10444 events [i].add = eb->add_method->mhandle;
10445 if (eb->remove_method)
10446 events [i].remove = eb->remove_method->mhandle;
10447 if (eb->raise_method)
10448 events [i].raise = eb->raise_method->mhandle;
10450 if (eb->other_methods) {
10451 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10452 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10453 MonoReflectionMethodBuilder *mb =
10454 mono_array_get (eb->other_methods,
10455 MonoReflectionMethodBuilder*, j);
10456 events [i].other [j] = mb->mhandle;
10459 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10464 remove_instantiations_of (gpointer key,
10466 gpointer user_data)
10468 MonoType *type = (MonoType*)key;
10469 MonoClass *klass = (MonoClass*)user_data;
10471 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10478 check_array_for_usertypes (MonoArray *arr)
10485 for (i = 0; i < mono_array_length (arr); ++i)
10486 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10489 MonoReflectionType*
10490 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10493 MonoDomain* domain;
10494 MonoReflectionType* res;
10497 MONO_ARCH_SAVE_REGS;
10499 domain = mono_object_domain (tb);
10500 klass = mono_class_from_mono_type (tb->type.type);
10503 * Check for user defined Type subclasses.
10505 RESOLVE_TYPE (tb->parent);
10506 check_array_for_usertypes (tb->interfaces);
10508 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10509 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10511 RESOLVE_TYPE (fb->type);
10512 check_array_for_usertypes (fb->modreq);
10513 check_array_for_usertypes (fb->modopt);
10514 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10515 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10520 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10521 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10523 RESOLVE_TYPE (mb->rtype);
10524 check_array_for_usertypes (mb->return_modreq);
10525 check_array_for_usertypes (mb->return_modopt);
10526 check_array_for_usertypes (mb->parameters);
10527 if (mb->param_modreq)
10528 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10529 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10530 if (mb->param_modopt)
10531 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10532 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10537 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10538 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10540 check_array_for_usertypes (mb->parameters);
10541 if (mb->param_modreq)
10542 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10543 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10544 if (mb->param_modopt)
10545 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10546 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10551 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10554 * we need to lock the domain because the lock will be taken inside
10555 * So, we need to keep the locking order correct.
10557 mono_loader_lock ();
10558 mono_domain_lock (domain);
10559 if (klass->wastypebuilder) {
10560 mono_domain_unlock (domain);
10561 mono_loader_unlock ();
10562 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10565 * Fields to set in klass:
10566 * the various flags: delegate/unicode/contextbound etc.
10568 klass->flags = tb->attrs;
10569 klass->has_cctor = 1;
10570 klass->has_finalize = 1;
10573 if (!((MonoDynamicImage*)klass->image)->run) {
10574 if (klass->generic_container) {
10575 /* FIXME: The code below can't handle generic classes */
10576 klass->wastypebuilder = TRUE;
10577 mono_loader_unlock ();
10578 mono_domain_unlock (domain);
10579 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10584 /* enums are done right away */
10585 if (!klass->enumtype)
10586 ensure_runtime_vtable (klass);
10588 if (tb->subtypes) {
10589 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10590 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10591 mono_class_alloc_ext (klass);
10592 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)));
10596 klass->nested_classes_inited = TRUE;
10598 /* fields and object layout */
10599 if (klass->parent) {
10600 if (!klass->parent->size_inited)
10601 mono_class_init (klass->parent);
10602 klass->instance_size = klass->parent->instance_size;
10603 klass->sizes.class_size = 0;
10604 klass->min_align = klass->parent->min_align;
10605 /* if the type has no fields we won't call the field_setup
10606 * routine which sets up klass->has_references.
10608 klass->has_references |= klass->parent->has_references;
10610 klass->instance_size = sizeof (MonoObject);
10611 klass->min_align = 1;
10614 /* FIXME: handle packing_size and instance_size */
10615 typebuilder_setup_fields (klass);
10617 typebuilder_setup_properties (klass);
10619 typebuilder_setup_events (klass);
10621 klass->wastypebuilder = TRUE;
10624 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10625 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10626 * we want to return normal System.MonoType objects, so clear these out from the cache.
10628 if (domain->type_hash && klass->generic_container)
10629 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10631 mono_domain_unlock (domain);
10632 mono_loader_unlock ();
10634 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10635 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10636 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10639 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10640 g_assert (res != (MonoReflectionType*)tb);
10646 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10648 MonoGenericParamFull *param;
10652 MONO_ARCH_SAVE_REGS;
10654 param = g_new0 (MonoGenericParamFull, 1);
10656 if (gparam->mbuilder) {
10657 if (!gparam->mbuilder->generic_container) {
10658 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10659 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10660 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10661 gparam->mbuilder->generic_container->is_method = TRUE;
10663 * Cannot set owner.method, since the MonoMethod is not created yet.
10664 * Set the image field instead, so type_in_image () works.
10666 gparam->mbuilder->generic_container->image = klass->image;
10668 param->param.owner = gparam->mbuilder->generic_container;
10669 } else if (gparam->tbuilder) {
10670 if (!gparam->tbuilder->generic_container) {
10671 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10672 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10673 gparam->tbuilder->generic_container->owner.klass = klass;
10675 param->param.owner = gparam->tbuilder->generic_container;
10678 param->info.name = mono_string_to_utf8 (gparam->name);
10679 param->param.num = gparam->index;
10681 image = &gparam->tbuilder->module->dynamic_image->image;
10682 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10684 gparam->type.type = &pklass->byval_arg;
10686 MOVING_GC_REGISTER (&pklass->reflection_info);
10687 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10688 mono_image_lock (image);
10689 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10690 mono_image_unlock (image);
10694 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10696 MonoReflectionModuleBuilder *module = sig->module;
10697 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10698 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10703 check_array_for_usertypes (sig->arguments);
10705 sigbuffer_init (&buf, 32);
10707 sigbuffer_add_value (&buf, 0x07);
10708 sigbuffer_add_value (&buf, na);
10709 if (assembly != NULL){
10710 for (i = 0; i < na; ++i) {
10711 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10712 encode_reflection_type (assembly, type, &buf);
10716 buflen = buf.p - buf.buf;
10717 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10718 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10719 sigbuffer_free (&buf);
10725 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10727 MonoDynamicImage *assembly = sig->module->dynamic_image;
10728 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10733 check_array_for_usertypes (sig->arguments);
10735 sigbuffer_init (&buf, 32);
10737 sigbuffer_add_value (&buf, 0x06);
10738 for (i = 0; i < na; ++i) {
10739 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10740 encode_reflection_type (assembly, type, &buf);
10743 buflen = buf.p - buf.buf;
10744 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10745 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10746 sigbuffer_free (&buf);
10752 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10754 ReflectionMethodBuilder rmb;
10755 MonoMethodSignature *sig;
10760 sig = dynamic_method_to_signature (mb);
10762 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10765 * Resolve references.
10768 * Every second entry in the refs array is reserved for storing handle_class,
10769 * which is needed by the ldtoken implementation in the JIT.
10771 rmb.nrefs = mb->nrefs;
10772 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10773 for (i = 0; i < mb->nrefs; i += 2) {
10774 MonoClass *handle_class;
10776 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10778 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10779 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10781 * The referenced DynamicMethod should already be created by the managed
10782 * code, except in the case of circular references. In that case, we store
10783 * method in the refs array, and fix it up later when the referenced
10784 * DynamicMethod is created.
10786 if (method->mhandle) {
10787 ref = method->mhandle;
10789 /* FIXME: GC object stored in unmanaged memory */
10792 /* FIXME: GC object stored in unmanaged memory */
10793 method->referenced_by = g_slist_append (method->referenced_by, mb);
10795 handle_class = mono_defaults.methodhandle_class;
10797 MonoException *ex = NULL;
10798 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10800 ex = mono_get_exception_type_load (NULL, NULL);
10801 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10802 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10806 mono_raise_exception (ex);
10811 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10812 rmb.refs [i + 1] = handle_class;
10815 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10817 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10819 /* Fix up refs entries pointing at us */
10820 for (l = mb->referenced_by; l; l = l->next) {
10821 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10822 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10825 g_assert (method->mhandle);
10827 data = (gpointer*)wrapper->method_data;
10828 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10829 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10830 data [i + 1] = mb->mhandle;
10833 g_slist_free (mb->referenced_by);
10837 /* ilgen is no longer needed */
10841 #endif /* DISABLE_REFLECTION_EMIT */
10844 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10849 mono_runtime_free_method (
10850 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10855 * mono_reflection_is_valid_dynamic_token:
10857 * Returns TRUE if token is valid.
10861 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10863 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10866 #ifndef DISABLE_REFLECTION_EMIT
10869 * mono_reflection_lookup_dynamic_token:
10871 * Finish the Builder object pointed to by TOKEN and return the corresponding
10872 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10873 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10876 * LOCKING: Take the loader lock
10879 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10881 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10885 mono_loader_lock ();
10886 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10887 mono_loader_unlock ();
10890 g_error ("Could not find required dynamic token 0x%08x", token);
10896 handle_class = &klass;
10897 return resolve_object (image, obj, handle_class, context);
10901 * ensure_complete_type:
10903 * Ensure that KLASS is completed if it is a dynamic type, or references
10907 ensure_complete_type (MonoClass *klass)
10909 if (klass->image->dynamic && !klass->wastypebuilder) {
10910 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10912 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10914 // Asserting here could break a lot of code
10915 //g_assert (klass->wastypebuilder);
10918 if (klass->generic_class) {
10919 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10922 for (i = 0; i < inst->type_argc; ++i) {
10923 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10929 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10931 gpointer result = NULL;
10933 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10934 result = mono_string_intern ((MonoString*)obj);
10935 *handle_class = NULL;
10937 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10938 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
10940 MonoType *inflated = mono_class_inflate_generic_type (type, context);
10941 result = mono_class_from_mono_type (inflated);
10942 mono_metadata_free_type (inflated);
10944 result = mono_class_from_mono_type (type);
10946 *handle_class = mono_defaults.typehandle_class;
10948 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10949 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10950 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10951 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10952 result = ((MonoReflectionMethod*)obj)->method;
10954 result = mono_class_inflate_generic_method (result, context);
10955 *handle_class = mono_defaults.methodhandle_class;
10957 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10958 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10959 result = mb->mhandle;
10961 /* Type is not yet created */
10962 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10964 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10967 * Hopefully this has been filled in by calling CreateType() on the
10971 * TODO: This won't work if the application finishes another
10972 * TypeBuilder instance instead of this one.
10974 result = mb->mhandle;
10977 result = mono_class_inflate_generic_method (result, context);
10978 *handle_class = mono_defaults.methodhandle_class;
10979 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10980 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10982 result = cb->mhandle;
10984 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10986 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10987 result = cb->mhandle;
10990 result = mono_class_inflate_generic_method (result, context);
10991 *handle_class = mono_defaults.methodhandle_class;
10992 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10993 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10995 ensure_complete_type (field->parent);
10997 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10998 MonoClass *class = mono_class_from_mono_type (inflated);
10999 MonoClassField *inflated_field;
11000 gpointer iter = NULL;
11001 mono_metadata_free_type (inflated);
11002 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11003 if (!strcmp (field->name, inflated_field->name))
11006 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11007 result = inflated_field;
11011 *handle_class = mono_defaults.fieldhandle_class;
11013 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11014 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11015 result = fb->handle;
11018 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11020 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11021 result = fb->handle;
11024 if (fb->handle && fb->handle->parent->generic_container) {
11025 MonoClass *klass = fb->handle->parent;
11026 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11027 MonoClass *inflated = mono_class_from_mono_type (type);
11029 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11031 mono_metadata_free_type (type);
11033 *handle_class = mono_defaults.fieldhandle_class;
11034 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11035 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11036 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11039 klass = type->data.klass;
11040 if (klass->wastypebuilder) {
11041 /* Already created */
11045 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11046 result = type->data.klass;
11049 *handle_class = mono_defaults.typehandle_class;
11050 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11051 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11052 MonoMethodSignature *sig;
11055 if (helper->arguments)
11056 nargs = mono_array_length (helper->arguments);
11060 sig = mono_metadata_signature_alloc (image, nargs);
11061 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11062 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11064 if (helper->call_conv == 0) /* unmanaged */
11065 sig->call_convention = helper->unmanaged_call_conv - 1;
11067 if (helper->call_conv & 0x02)
11068 sig->call_convention = MONO_CALL_VARARG;
11070 sig->call_convention = MONO_CALL_DEFAULT;
11072 sig->param_count = nargs;
11073 /* TODO: Copy type ? */
11074 sig->ret = helper->return_type->type;
11075 for (i = 0; i < nargs; ++i)
11076 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11079 *handle_class = NULL;
11080 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11081 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11082 /* Already created by the managed code */
11083 g_assert (method->mhandle);
11084 result = method->mhandle;
11085 *handle_class = mono_defaults.methodhandle_class;
11086 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11087 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11088 type = mono_class_inflate_generic_type (type, context);
11089 result = mono_class_from_mono_type (type);
11090 *handle_class = mono_defaults.typehandle_class;
11092 mono_metadata_free_type (type);
11093 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11094 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11095 type = mono_class_inflate_generic_type (type, context);
11096 result = mono_class_from_mono_type (type);
11097 *handle_class = mono_defaults.typehandle_class;
11099 mono_metadata_free_type (type);
11100 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11101 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11102 MonoClass *inflated;
11105 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11106 inflated = mono_class_from_mono_type (type);
11108 g_assert (f->fb->handle);
11109 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11111 mono_metadata_free_type (type);
11112 *handle_class = mono_defaults.fieldhandle_class;
11113 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11114 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11115 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11116 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11117 g_assert (c->cb->mhandle);
11118 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11119 *handle_class = mono_defaults.methodhandle_class;
11120 mono_metadata_free_type (type);
11121 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11122 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11123 if (m->method_args) {
11124 result = mono_reflection_method_on_tb_inst_get_handle (m);
11126 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11127 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11128 g_assert (m->mb->mhandle);
11129 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11130 mono_metadata_free_type (type);
11132 *handle_class = mono_defaults.methodhandle_class;
11133 } else if (is_sre_array (mono_object_get_class(obj)) ||
11134 is_sre_byref (mono_object_get_class(obj)) ||
11135 is_sre_pointer (mono_object_get_class(obj))) {
11136 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11137 MonoType *type = mono_reflection_type_get_handle (ref_type);
11138 result = mono_class_from_mono_type (type);
11139 *handle_class = mono_defaults.typehandle_class;
11141 g_print ("%s\n", obj->vtable->klass->name);
11142 g_assert_not_reached ();
11147 #else /* DISABLE_REFLECTION_EMIT */
11150 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11152 g_assert_not_reached ();
11157 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11159 g_assert_not_reached ();
11163 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11165 g_assert_not_reached ();
11169 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11171 g_assert_not_reached ();
11175 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11177 g_assert_not_reached ();
11181 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11183 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11187 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11189 g_assert_not_reached ();
11193 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11195 g_assert_not_reached ();
11198 MonoReflectionModule *
11199 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11201 g_assert_not_reached ();
11206 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11208 g_assert_not_reached ();
11213 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11215 g_assert_not_reached ();
11220 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11221 gboolean create_methodspec, gboolean register_token)
11223 g_assert_not_reached ();
11228 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11233 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11234 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11237 g_assert_not_reached ();
11241 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11244 *num_overrides = 0;
11247 MonoReflectionEvent *
11248 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11250 g_assert_not_reached ();
11254 MonoReflectionType*
11255 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11257 g_assert_not_reached ();
11262 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11264 g_assert_not_reached ();
11268 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11270 g_assert_not_reached ();
11275 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11277 g_assert_not_reached ();
11282 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11287 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11293 mono_reflection_type_get_handle (MonoReflectionType* ref)
11300 #endif /* DISABLE_REFLECTION_EMIT */
11302 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11303 const static guint32 declsec_flags_map[] = {
11304 0x00000000, /* empty */
11305 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11306 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11307 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11308 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11309 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11310 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11311 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11312 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11313 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11314 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11315 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11316 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11317 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11318 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11319 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11320 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11321 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11322 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11326 * Returns flags that includes all available security action associated to the handle.
11327 * @token: metadata token (either for a class or a method)
11328 * @image: image where resides the metadata.
11331 mono_declsec_get_flags (MonoImage *image, guint32 token)
11333 int index = mono_metadata_declsec_from_index (image, token);
11334 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11335 guint32 result = 0;
11339 /* HasSecurity can be present for other, not specially encoded, attributes,
11340 e.g. SuppressUnmanagedCodeSecurityAttribute */
11344 for (i = index; i < t->rows; i++) {
11345 guint32 cols [MONO_DECL_SECURITY_SIZE];
11347 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11348 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11351 action = cols [MONO_DECL_SECURITY_ACTION];
11352 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11353 result |= declsec_flags_map [action];
11355 g_assert_not_reached ();
11362 * Get the security actions (in the form of flags) associated with the specified method.
11364 * @method: The method for which we want the declarative security flags.
11365 * Return the declarative security flags for the method (only).
11367 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11368 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11371 mono_declsec_flags_from_method (MonoMethod *method)
11373 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11374 /* FIXME: No cache (for the moment) */
11375 guint32 idx = mono_method_get_index (method);
11376 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11377 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11378 return mono_declsec_get_flags (method->klass->image, idx);
11384 * Get the security actions (in the form of flags) associated with the specified class.
11386 * @klass: The class for which we want the declarative security flags.
11387 * Return the declarative security flags for the class.
11389 * Note: We cache the flags inside the MonoClass structure as this will get
11390 * called very often (at least for each method).
11393 mono_declsec_flags_from_class (MonoClass *klass)
11395 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11396 if (!klass->ext || !klass->ext->declsec_flags) {
11399 idx = mono_metadata_token_index (klass->type_token);
11400 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11401 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11402 mono_loader_lock ();
11403 mono_class_alloc_ext (klass);
11404 mono_loader_unlock ();
11405 /* we cache the flags on classes */
11406 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11408 return klass->ext->declsec_flags;
11414 * Get the security actions (in the form of flags) associated with the specified assembly.
11416 * @assembly: The assembly for which we want the declarative security flags.
11417 * Return the declarative security flags for the assembly.
11420 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11422 guint32 idx = 1; /* there is only one assembly */
11423 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11424 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11425 return mono_declsec_get_flags (assembly->image, idx);
11430 * Fill actions for the specific index (which may either be an encoded class token or
11431 * an encoded method token) from the metadata image.
11432 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11435 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11436 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11438 MonoBoolean result = FALSE;
11440 guint32 cols [MONO_DECL_SECURITY_SIZE];
11441 int index = mono_metadata_declsec_from_index (image, token);
11444 t = &image->tables [MONO_TABLE_DECLSECURITY];
11445 for (i = index; i < t->rows; i++) {
11446 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11448 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11451 /* if present only replace (class) permissions with method permissions */
11452 /* if empty accept either class or method permissions */
11453 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11454 if (!actions->demand.blob) {
11455 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11456 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11457 actions->demand.blob = (char*) (blob + 2);
11458 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11461 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11462 if (!actions->noncasdemand.blob) {
11463 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11464 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11465 actions->noncasdemand.blob = (char*) (blob + 2);
11466 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11469 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11470 if (!actions->demandchoice.blob) {
11471 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11472 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11473 actions->demandchoice.blob = (char*) (blob + 2);
11474 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11484 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11485 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11487 guint32 idx = mono_metadata_token_index (klass->type_token);
11488 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11489 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11490 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11494 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11495 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11497 guint32 idx = mono_method_get_index (method);
11498 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11499 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11500 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11504 * Collect all actions (that requires to generate code in mini) assigned for
11505 * the specified method.
11506 * Note: Don't use the content of actions if the function return FALSE.
11509 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11511 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11512 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11513 MonoBoolean result = FALSE;
11516 /* quick exit if no declarative security is present in the metadata */
11517 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11520 /* we want the original as the wrapper is "free" of the security informations */
11521 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11522 method = mono_marshal_method_from_wrapper (method);
11527 /* First we look for method-level attributes */
11528 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11529 mono_class_init (method->klass);
11530 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11532 result = mono_declsec_get_method_demands_params (method, demands,
11533 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11536 /* Here we use (or create) the class declarative cache to look for demands */
11537 flags = mono_declsec_flags_from_class (method->klass);
11538 if (flags & mask) {
11540 mono_class_init (method->klass);
11541 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11543 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11544 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11547 /* The boolean return value is used as a shortcut in case nothing needs to
11548 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11554 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11556 * Note: Don't use the content of actions if the function return FALSE.
11559 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11561 MonoBoolean result = FALSE;
11564 /* quick exit if no declarative security is present in the metadata */
11565 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11568 /* we want the original as the wrapper is "free" of the security informations */
11569 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11570 method = mono_marshal_method_from_wrapper (method);
11575 /* results are independant - zeroize both */
11576 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11577 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11579 /* First we look for method-level attributes */
11580 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11581 mono_class_init (method->klass);
11583 result = mono_declsec_get_method_demands_params (method, cmethod,
11584 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11587 /* Here we use (or create) the class declarative cache to look for demands */
11588 flags = mono_declsec_flags_from_class (method->klass);
11589 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11590 mono_class_init (method->klass);
11592 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11593 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11600 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11602 * @klass The inherited class - this is the class that provides the security check (attributes)
11604 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11606 * Note: Don't use the content of actions if the function return FALSE.
11609 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11611 MonoBoolean result = FALSE;
11614 /* quick exit if no declarative security is present in the metadata */
11615 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11618 /* Here we use (or create) the class declarative cache to look for demands */
11619 flags = mono_declsec_flags_from_class (klass);
11620 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11621 mono_class_init (klass);
11622 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11624 result |= mono_declsec_get_class_demands_params (klass, demands,
11625 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11632 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11634 * Note: Don't use the content of actions if the function return FALSE.
11637 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11639 /* quick exit if no declarative security is present in the metadata */
11640 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11643 /* we want the original as the wrapper is "free" of the security informations */
11644 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11645 method = mono_marshal_method_from_wrapper (method);
11650 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11651 mono_class_init (method->klass);
11652 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11654 return mono_declsec_get_method_demands_params (method, demands,
11655 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11662 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11664 guint32 cols [MONO_DECL_SECURITY_SIZE];
11668 int index = mono_metadata_declsec_from_index (image, token);
11672 t = &image->tables [MONO_TABLE_DECLSECURITY];
11673 for (i = index; i < t->rows; i++) {
11674 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11676 /* shortcut - index are ordered */
11677 if (token != cols [MONO_DECL_SECURITY_PARENT])
11680 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11681 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11682 entry->blob = (char*) (metadata + 2);
11683 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11692 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11694 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11695 guint32 idx = mono_method_get_index (method);
11696 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11697 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11698 return get_declsec_action (method->klass->image, idx, action, entry);
11704 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11707 guint32 flags = mono_declsec_flags_from_class (klass);
11708 if (declsec_flags_map [action] & flags) {
11709 guint32 idx = mono_metadata_token_index (klass->type_token);
11710 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11711 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11712 return get_declsec_action (klass->image, idx, action, entry);
11718 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11720 guint32 idx = 1; /* there is only one assembly */
11721 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11722 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11724 return get_declsec_action (assembly->image, idx, action, entry);
11728 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11730 MonoObject *res, *exc;
11732 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11733 static MonoMethod *method = NULL;
11735 if (!System_Reflection_Emit_TypeBuilder) {
11736 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11737 g_assert (System_Reflection_Emit_TypeBuilder);
11739 if (method == NULL) {
11740 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11745 * The result of mono_type_get_object () might be a System.MonoType but we
11746 * need a TypeBuilder so use klass->reflection_info.
11748 g_assert (klass->reflection_info);
11749 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11751 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11753 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11757 return *(MonoBoolean*)mono_object_unbox (res);