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