2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/utils/mono-string.h>
44 static void* reflection_info_desc = NULL;
45 #define MOVING_GC_REGISTER(addr) do { \
46 if (!reflection_info_desc) { \
48 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
50 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
53 #define MOVING_GC_REGISTER(addr)
62 #define TEXT_OFFSET 512
63 #define CLI_H_SIZE 136
64 #define FILE_ALIGN 512
65 #define VIRT_ALIGN 8192
66 #define START_TEXT_RVA 0x00002000
69 MonoReflectionILGen *ilgen;
70 MonoReflectionType *rtype;
71 MonoArray *parameters;
72 MonoArray *generic_params;
73 MonoGenericContainer *generic_container;
79 guint32 *table_idx; /* note: it's a pointer */
83 MonoBoolean init_locals;
84 MonoBoolean skip_visibility;
85 MonoArray *return_modreq;
86 MonoArray *return_modopt;
87 MonoArray *param_modreq;
88 MonoArray *param_modopt;
89 MonoArray *permissions;
94 int charset, extra_flags, native_cc;
95 MonoString *dll, *dllentry;
96 } ReflectionMethodBuilder;
100 MonoReflectionGenericParam *gparam;
101 } GenericParamTableEntry;
103 const unsigned char table_sizes [MONO_TABLE_NUM] = {
113 MONO_INTERFACEIMPL_SIZE,
114 MONO_MEMBERREF_SIZE, /* 0x0A */
116 MONO_CUSTOM_ATTR_SIZE,
117 MONO_FIELD_MARSHAL_SIZE,
118 MONO_DECL_SECURITY_SIZE,
119 MONO_CLASS_LAYOUT_SIZE,
120 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
121 MONO_STAND_ALONE_SIGNATURE_SIZE,
125 MONO_PROPERTY_MAP_SIZE,
128 MONO_METHOD_SEMA_SIZE,
129 MONO_METHODIMPL_SIZE,
130 MONO_MODULEREF_SIZE, /* 0x1A */
136 MONO_ASSEMBLY_SIZE, /* 0x20 */
137 MONO_ASSEMBLY_PROCESSOR_SIZE,
138 MONO_ASSEMBLYOS_SIZE,
139 MONO_ASSEMBLYREF_SIZE,
140 MONO_ASSEMBLYREFPROC_SIZE,
141 MONO_ASSEMBLYREFOS_SIZE,
145 MONO_NESTED_CLASS_SIZE,
147 MONO_GENERICPARAM_SIZE, /* 0x2A */
148 MONO_METHODSPEC_SIZE,
149 MONO_GENPARCONSTRAINT_SIZE
153 #ifndef DISABLE_REFLECTION_EMIT
154 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
155 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
156 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
157 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
158 static void ensure_runtime_vtable (MonoClass *klass);
159 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
160 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
161 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
162 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
165 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
166 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
167 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
168 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
169 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
170 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
171 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
172 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
173 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
174 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
175 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
176 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
177 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
178 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
179 static gboolean is_sre_array (MonoClass *class);
180 static gboolean is_sre_byref (MonoClass *class);
181 static gboolean is_sre_pointer (MonoClass *class);
182 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
183 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
184 static MonoMethod * inflate_method (MonoReflectionGenericClass *type, MonoObject *obj);
186 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
187 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
188 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
189 __type = mono_reflection_type_resolve_user_types (__type); \
190 mono_array_set (arr, MonoReflectionType*, index, __type); \
193 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
196 mono_reflection_init (void)
201 sigbuffer_init (SigBuffer *buf, int size)
203 buf->buf = g_malloc (size);
205 buf->end = buf->buf + size;
209 sigbuffer_make_room (SigBuffer *buf, int size)
211 if (buf->end - buf->p < size) {
212 int new_size = buf->end - buf->buf + size + 32;
213 char *p = g_realloc (buf->buf, new_size);
214 size = buf->p - buf->buf;
217 buf->end = buf->buf + new_size;
222 sigbuffer_add_value (SigBuffer *buf, guint32 val)
224 sigbuffer_make_room (buf, 6);
225 mono_metadata_encode_value (val, buf->p, &buf->p);
229 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
231 sigbuffer_make_room (buf, 1);
237 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
239 sigbuffer_make_room (buf, size);
240 memcpy (buf->p, p, size);
245 sigbuffer_free (SigBuffer *buf)
250 #ifndef DISABLE_REFLECTION_EMIT
254 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
258 image_g_malloc (MonoImage *image, guint size)
261 return mono_image_alloc (image, size);
263 return g_malloc (size);
265 #endif /* !DISABLE_REFLECTION_EMIT */
270 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
274 image_g_malloc0 (MonoImage *image, guint size)
277 return mono_image_alloc0 (image, size);
279 return g_malloc0 (size);
282 #ifndef DISABLE_REFLECTION_EMIT
284 image_strdup (MonoImage *image, const char *s)
287 return mono_image_strdup (image, s);
293 #define image_g_new(image,struct_type, n_structs) \
294 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
296 #define image_g_new0(image,struct_type, n_structs) \
297 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
301 alloc_table (MonoDynamicTable *table, guint nrows)
304 g_assert (table->columns);
305 if (nrows + 1 >= table->alloc_rows) {
306 while (nrows + 1 >= table->alloc_rows) {
307 if (table->alloc_rows == 0)
308 table->alloc_rows = 16;
310 table->alloc_rows *= 2;
313 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
318 make_room_in_stream (MonoDynamicStream *stream, int size)
320 if (size <= stream->alloc_size)
323 while (stream->alloc_size <= size) {
324 if (stream->alloc_size < 4096)
325 stream->alloc_size = 4096;
327 stream->alloc_size *= 2;
330 stream->data = g_realloc (stream->data, stream->alloc_size);
334 string_heap_insert (MonoDynamicStream *sh, const char *str)
338 gpointer oldkey, oldval;
340 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
341 return GPOINTER_TO_UINT (oldval);
343 len = strlen (str) + 1;
346 make_room_in_stream (sh, idx + len);
349 * We strdup the string even if we already copy them in sh->data
350 * so that the string pointers in the hash remain valid even if
351 * we need to realloc sh->data. We may want to avoid that later.
353 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
354 memcpy (sh->data + idx, str, len);
360 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
362 char *name = mono_string_to_utf8 (str);
364 idx = string_heap_insert (sh, name);
369 #ifndef DISABLE_REFLECTION_EMIT
371 string_heap_init (MonoDynamicStream *sh)
374 sh->alloc_size = 4096;
375 sh->data = g_malloc (4096);
376 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
377 string_heap_insert (sh, "");
382 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
386 make_room_in_stream (stream, stream->index + len);
387 memcpy (stream->data + stream->index, data, len);
389 stream->index += len;
391 * align index? Not without adding an additional param that controls it since
392 * we may store a blob value in pieces.
398 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
402 make_room_in_stream (stream, stream->index + len);
403 memset (stream->data + stream->index, 0, len);
405 stream->index += len;
410 stream_data_align (MonoDynamicStream *stream)
413 guint32 count = stream->index % 4;
415 /* we assume the stream data will be aligned */
417 mono_image_add_stream_data (stream, buf, 4 - count);
420 #ifndef DISABLE_REFLECTION_EMIT
422 mono_blob_entry_hash (const char* str)
426 len = mono_metadata_decode_blob_size (str, &str);
430 for (str += 1; str < end; str++)
431 h = (h << 5) - h + *str;
439 mono_blob_entry_equal (const char *str1, const char *str2) {
443 len = mono_metadata_decode_blob_size (str1, &end1);
444 len2 = mono_metadata_decode_blob_size (str2, &end2);
447 return memcmp (end1, end2, len) == 0;
451 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
455 gpointer oldkey, oldval;
457 copy = g_malloc (s1+s2);
458 memcpy (copy, b1, s1);
459 memcpy (copy + s1, b2, s2);
460 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
462 idx = GPOINTER_TO_UINT (oldval);
464 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
465 mono_image_add_stream_data (&assembly->blob, b2, s2);
466 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
472 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
476 guint32 size = buf->p - buf->buf;
478 g_assert (size <= (buf->end - buf->buf));
479 mono_metadata_encode_value (size, b, &b);
480 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
484 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
485 * dest may be misaligned.
488 swap_with_size (char *dest, const char* val, int len, int nelem) {
489 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
492 for (elem = 0; elem < nelem; ++elem) {
518 g_assert_not_reached ();
524 memcpy (dest, val, len * nelem);
529 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
533 guint32 idx = 0, len;
535 len = str->length * 2;
536 mono_metadata_encode_value (len, b, &b);
537 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
539 char *swapped = g_malloc (2 * mono_string_length (str));
540 const char *p = (const char*)mono_string_chars (str);
542 swap_with_size (swapped, p, 2, mono_string_length (str));
543 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
547 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
552 #ifndef DISABLE_REFLECTION_EMIT
554 default_class_from_mono_type (MonoType *type)
556 switch (type->type) {
557 case MONO_TYPE_OBJECT:
558 return mono_defaults.object_class;
560 return mono_defaults.void_class;
561 case MONO_TYPE_BOOLEAN:
562 return mono_defaults.boolean_class;
564 return mono_defaults.char_class;
566 return mono_defaults.sbyte_class;
568 return mono_defaults.byte_class;
570 return mono_defaults.int16_class;
572 return mono_defaults.uint16_class;
574 return mono_defaults.int32_class;
576 return mono_defaults.uint32_class;
578 return mono_defaults.int_class;
580 return mono_defaults.uint_class;
582 return mono_defaults.int64_class;
584 return mono_defaults.uint64_class;
586 return mono_defaults.single_class;
588 return mono_defaults.double_class;
589 case MONO_TYPE_STRING:
590 return mono_defaults.string_class;
592 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
593 g_assert_not_reached ();
601 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
604 MonoGenericInst *class_inst;
609 class_inst = gclass->context.class_inst;
611 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
612 klass = gclass->container_class;
613 sigbuffer_add_value (buf, klass->byval_arg.type);
614 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
616 sigbuffer_add_value (buf, class_inst->type_argc);
617 for (i = 0; i < class_inst->type_argc; ++i)
618 encode_type (assembly, class_inst->type_argv [i], buf);
623 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
626 g_assert_not_reached ();
631 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
635 case MONO_TYPE_BOOLEAN:
649 case MONO_TYPE_STRING:
650 case MONO_TYPE_OBJECT:
651 case MONO_TYPE_TYPEDBYREF:
652 sigbuffer_add_value (buf, type->type);
655 sigbuffer_add_value (buf, type->type);
656 encode_type (assembly, type->data.type, buf);
658 case MONO_TYPE_SZARRAY:
659 sigbuffer_add_value (buf, type->type);
660 encode_type (assembly, &type->data.klass->byval_arg, buf);
662 case MONO_TYPE_VALUETYPE:
663 case MONO_TYPE_CLASS: {
664 MonoClass *k = mono_class_from_mono_type (type);
666 if (k->generic_container) {
667 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
668 encode_generic_class (assembly, gclass, buf);
671 * Make sure we use the correct type.
673 sigbuffer_add_value (buf, k->byval_arg.type);
675 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
676 * otherwise two typerefs could point to the same type, leading to
677 * verification errors.
679 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
683 case MONO_TYPE_ARRAY:
684 sigbuffer_add_value (buf, type->type);
685 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
686 sigbuffer_add_value (buf, type->data.array->rank);
687 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
688 sigbuffer_add_value (buf, 0);
690 case MONO_TYPE_GENERICINST:
691 encode_generic_class (assembly, type->data.generic_class, buf);
695 sigbuffer_add_value (buf, type->type);
696 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
699 g_error ("need to encode type %x", type->type);
704 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
707 sigbuffer_add_value (buf, MONO_TYPE_VOID);
711 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
715 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
720 for (i = 0; i < mono_array_length (modreq); ++i) {
721 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
722 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
723 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
727 for (i = 0; i < mono_array_length (modopt); ++i) {
728 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
729 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
730 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
735 #ifndef DISABLE_REFLECTION_EMIT
737 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
741 guint32 nparams = sig->param_count;
747 sigbuffer_init (&buf, 32);
749 * FIXME: vararg, explicit_this, differenc call_conv values...
751 idx = sig->call_convention;
753 idx |= 0x20; /* hasthis */
754 if (sig->generic_param_count)
755 idx |= 0x10; /* generic */
756 sigbuffer_add_byte (&buf, idx);
757 if (sig->generic_param_count)
758 sigbuffer_add_value (&buf, sig->generic_param_count);
759 sigbuffer_add_value (&buf, nparams);
760 encode_type (assembly, sig->ret, &buf);
761 for (i = 0; i < nparams; ++i) {
762 if (i == sig->sentinelpos)
763 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
764 encode_type (assembly, sig->params [i], &buf);
766 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
767 sigbuffer_free (&buf);
773 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
776 * FIXME: reuse code from method_encode_signature().
780 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
781 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
782 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
785 sigbuffer_init (&buf, 32);
786 /* LAMESPEC: all the call conv spec is foobared */
787 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
788 if (mb->call_conv & 2)
789 idx |= 0x5; /* vararg */
790 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
791 idx |= 0x20; /* hasthis */
793 idx |= 0x10; /* generic */
794 sigbuffer_add_byte (&buf, idx);
796 sigbuffer_add_value (&buf, ngparams);
797 sigbuffer_add_value (&buf, nparams + notypes);
798 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
799 encode_reflection_type (assembly, mb->rtype, &buf);
800 for (i = 0; i < nparams; ++i) {
801 MonoArray *modreq = NULL;
802 MonoArray *modopt = NULL;
803 MonoReflectionType *pt;
805 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
806 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
807 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
808 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
809 encode_custom_modifiers (assembly, modreq, modopt, &buf);
810 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
811 encode_reflection_type (assembly, pt, &buf);
814 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
815 for (i = 0; i < notypes; ++i) {
816 MonoReflectionType *pt;
818 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
819 encode_reflection_type (assembly, pt, &buf);
822 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
823 sigbuffer_free (&buf);
828 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
830 MonoDynamicTable *table;
832 guint32 idx, sig_idx;
833 guint nl = mono_array_length (ilgen->locals);
837 sigbuffer_init (&buf, 32);
838 sigbuffer_add_value (&buf, 0x07);
839 sigbuffer_add_value (&buf, nl);
840 for (i = 0; i < nl; ++i) {
841 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
844 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
846 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
848 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
849 sigbuffer_free (&buf);
851 if (assembly->standalonesig_cache == NULL)
852 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
853 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
857 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
858 idx = table->next_idx ++;
860 alloc_table (table, table->rows);
861 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
863 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
865 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
871 method_count_clauses (MonoReflectionILGen *ilgen)
873 guint32 num_clauses = 0;
876 MonoILExceptionInfo *ex_info;
877 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
878 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
879 if (ex_info->handlers)
880 num_clauses += mono_array_length (ex_info->handlers);
888 #ifndef DISABLE_REFLECTION_EMIT
889 static MonoExceptionClause*
890 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
892 MonoExceptionClause *clauses;
893 MonoExceptionClause *clause;
894 MonoILExceptionInfo *ex_info;
895 MonoILExceptionBlock *ex_block;
896 guint32 finally_start;
897 int i, j, clause_index;;
899 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
902 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
903 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
904 finally_start = ex_info->start + ex_info->len;
905 if (!ex_info->handlers)
907 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
908 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
909 clause = &(clauses [clause_index]);
911 clause->flags = ex_block->type;
912 clause->try_offset = ex_info->start;
914 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
915 clause->try_len = finally_start - ex_info->start;
917 clause->try_len = ex_info->len;
918 clause->handler_offset = ex_block->start;
919 clause->handler_len = ex_block->len;
920 if (ex_block->extype) {
921 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
923 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
924 clause->data.filter_offset = ex_block->filter_offset;
926 clause->data.filter_offset = 0;
928 finally_start = ex_block->start + ex_block->len;
936 #endif /* !DISABLE_REFLECTION_EMIT */
939 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
945 gint32 num_locals = 0;
946 gint32 num_exception = 0;
949 char fat_header [12];
952 guint32 local_sig = 0;
953 guint32 header_size = 12;
956 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
957 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
961 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
963 code = mb->ilgen->code;
964 code_size = mb->ilgen->code_len;
965 max_stack = mb->ilgen->max_stack;
966 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
967 if (mb->ilgen->ex_handlers)
968 num_exception = method_count_clauses (mb->ilgen);
972 char *name = mono_string_to_utf8 (mb->name);
973 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
974 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
977 mono_raise_exception (exception);
980 code_size = mono_array_length (code);
981 max_stack = 8; /* we probably need to run a verifier on the code... */
984 stream_data_align (&assembly->code);
986 /* check for exceptions, maxstack, locals */
987 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
989 if (code_size < 64 && !(code_size & 1)) {
990 flags = (code_size << 2) | 0x2;
991 } else if (code_size < 32 && (code_size & 1)) {
992 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
996 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
997 /* add to the fixup todo list */
998 if (mb->ilgen && mb->ilgen->num_token_fixups)
999 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1000 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1001 return assembly->text_rva + idx;
1005 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1007 * FIXME: need to set also the header size in fat_flags.
1008 * (and more sects and init locals flags)
1012 fat_flags |= METHOD_HEADER_MORE_SECTS;
1013 if (mb->init_locals)
1014 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1015 fat_header [0] = fat_flags;
1016 fat_header [1] = (header_size / 4 ) << 4;
1017 short_value = GUINT16_TO_LE (max_stack);
1018 memcpy (fat_header + 2, &short_value, 2);
1019 int_value = GUINT32_TO_LE (code_size);
1020 memcpy (fat_header + 4, &int_value, 4);
1021 int_value = GUINT32_TO_LE (local_sig);
1022 memcpy (fat_header + 8, &int_value, 4);
1023 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1024 /* add to the fixup todo list */
1025 if (mb->ilgen && mb->ilgen->num_token_fixups)
1026 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1028 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1029 if (num_exception) {
1030 unsigned char sheader [4];
1031 MonoILExceptionInfo * ex_info;
1032 MonoILExceptionBlock * ex_block;
1035 stream_data_align (&assembly->code);
1036 /* always use fat format for now */
1037 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1038 num_exception *= 6 * sizeof (guint32);
1039 num_exception += 4; /* include the size of the header */
1040 sheader [1] = num_exception & 0xff;
1041 sheader [2] = (num_exception >> 8) & 0xff;
1042 sheader [3] = (num_exception >> 16) & 0xff;
1043 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1044 /* fat header, so we are already aligned */
1046 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1047 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1048 if (ex_info->handlers) {
1049 int finally_start = ex_info->start + ex_info->len;
1050 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1052 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1054 val = GUINT32_TO_LE (ex_block->type);
1055 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057 val = GUINT32_TO_LE (ex_info->start);
1058 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 /* need fault, too, probably */
1060 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1061 val = GUINT32_TO_LE (finally_start - ex_info->start);
1063 val = GUINT32_TO_LE (ex_info->len);
1064 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1065 /* handler offset */
1066 val = GUINT32_TO_LE (ex_block->start);
1067 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1069 val = GUINT32_TO_LE (ex_block->len);
1070 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1071 finally_start = ex_block->start + ex_block->len;
1072 if (ex_block->extype) {
1073 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1075 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1076 val = ex_block->filter_offset;
1080 val = GUINT32_TO_LE (val);
1081 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1082 /*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",
1083 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);*/
1086 g_error ("No clauses for ex info block %d", i);
1090 return assembly->text_rva + idx;
1094 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1097 MonoDynamicTable *table;
1100 table = &assembly->tables [table_idx];
1102 g_assert (col < table->columns);
1104 values = table->values + table->columns;
1105 for (i = 1; i <= table->rows; ++i) {
1106 if (values [col] == token)
1108 values += table->columns;
1114 * LOCKING: Acquires the loader lock.
1116 static MonoCustomAttrInfo*
1117 lookup_custom_attr (MonoImage *image, gpointer member)
1119 MonoCustomAttrInfo* res;
1121 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1126 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1130 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1132 /* FIXME: Need to do more checks */
1133 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1134 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1136 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1143 static MonoCustomAttrInfo*
1144 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1146 int i, index, count, not_visible;
1147 MonoCustomAttrInfo *ainfo;
1148 MonoReflectionCustomAttr *cattr;
1152 /* FIXME: check in assembly the Run flag is set */
1154 count = mono_array_length (cattrs);
1156 /* Skip nonpublic attributes since MS.NET seems to do the same */
1157 /* FIXME: This needs to be done more globally */
1159 for (i = 0; i < count; ++i) {
1160 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1161 if (!custom_attr_visible (image, cattr))
1164 count -= not_visible;
1166 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1168 ainfo->image = image;
1169 ainfo->num_attrs = count;
1170 ainfo->cached = alloc_img != NULL;
1172 for (i = 0; i < count; ++i) {
1173 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1174 if (custom_attr_visible (image, cattr)) {
1175 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1176 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1177 ainfo->attrs [index].ctor = cattr->ctor->method;
1178 ainfo->attrs [index].data = saved;
1179 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1187 #ifndef DISABLE_REFLECTION_EMIT
1189 * LOCKING: Acquires the loader lock.
1192 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1194 MonoCustomAttrInfo *ainfo, *tmp;
1196 if (!cattrs || !mono_array_length (cattrs))
1199 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1201 mono_loader_lock ();
1202 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1204 mono_custom_attrs_free (tmp);
1205 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1206 mono_loader_unlock ();
1212 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1219 * idx is the table index of the object
1220 * type is one of MONO_CUSTOM_ATTR_*
1223 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1225 MonoDynamicTable *table;
1226 MonoReflectionCustomAttr *cattr;
1228 guint32 count, i, token;
1230 char *p = blob_size;
1232 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1235 count = mono_array_length (cattrs);
1236 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1237 table->rows += count;
1238 alloc_table (table, table->rows);
1239 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1240 idx <<= MONO_CUSTOM_ATTR_BITS;
1242 for (i = 0; i < count; ++i) {
1243 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1244 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1245 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1246 type = mono_metadata_token_index (token);
1247 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1248 switch (mono_metadata_token_table (token)) {
1249 case MONO_TABLE_METHOD:
1250 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1252 case MONO_TABLE_MEMBERREF:
1253 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1256 g_warning ("got wrong token in custom attr");
1259 values [MONO_CUSTOM_ATTR_TYPE] = type;
1261 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1262 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1263 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1264 values += MONO_CUSTOM_ATTR_SIZE;
1270 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1272 MonoDynamicTable *table;
1274 guint32 count, i, idx;
1275 MonoReflectionPermissionSet *perm;
1280 count = mono_array_length (permissions);
1281 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1282 table->rows += count;
1283 alloc_table (table, table->rows);
1285 for (i = 0; i < mono_array_length (permissions); ++i) {
1286 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1288 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1290 idx = mono_metadata_token_index (parent_token);
1291 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1292 switch (mono_metadata_token_table (parent_token)) {
1293 case MONO_TABLE_TYPEDEF:
1294 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1296 case MONO_TABLE_METHOD:
1297 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1299 case MONO_TABLE_ASSEMBLY:
1300 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1303 g_assert_not_reached ();
1306 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1307 values [MONO_DECL_SECURITY_PARENT] = idx;
1308 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1315 * Fill in the MethodDef and ParamDef tables for a method.
1316 * This is used for both normal methods and constructors.
1319 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1321 MonoDynamicTable *table;
1325 /* room in this table is already allocated */
1326 table = &assembly->tables [MONO_TABLE_METHOD];
1327 *mb->table_idx = table->next_idx ++;
1328 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1329 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1330 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1331 values [MONO_METHOD_FLAGS] = mb->attrs;
1332 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1333 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1334 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1336 table = &assembly->tables [MONO_TABLE_PARAM];
1337 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1339 mono_image_add_decl_security (assembly,
1340 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1343 MonoDynamicTable *mtable;
1346 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1347 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1350 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1351 if (mono_array_get (mb->pinfo, gpointer, i))
1354 table->rows += count;
1355 alloc_table (table, table->rows);
1356 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1357 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1358 MonoReflectionParamBuilder *pb;
1359 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1360 values [MONO_PARAM_FLAGS] = pb->attrs;
1361 values [MONO_PARAM_SEQUENCE] = i;
1362 if (pb->name != NULL) {
1363 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1365 values [MONO_PARAM_NAME] = 0;
1367 values += MONO_PARAM_SIZE;
1368 if (pb->marshal_info) {
1370 alloc_table (mtable, mtable->rows);
1371 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1372 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1373 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1375 pb->table_idx = table->next_idx++;
1376 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1377 guint32 field_type = 0;
1378 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1380 alloc_table (mtable, mtable->rows);
1381 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1382 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1383 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1384 mvalues [MONO_CONSTANT_TYPE] = field_type;
1385 mvalues [MONO_CONSTANT_PADDING] = 0;
1393 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1395 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1397 rmb->ilgen = mb->ilgen;
1398 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1399 rmb->parameters = mb->parameters;
1400 rmb->generic_params = mb->generic_params;
1401 rmb->generic_container = mb->generic_container;
1402 rmb->opt_types = NULL;
1403 rmb->pinfo = mb->pinfo;
1404 rmb->attrs = mb->attrs;
1405 rmb->iattrs = mb->iattrs;
1406 rmb->call_conv = mb->call_conv;
1407 rmb->code = mb->code;
1408 rmb->type = mb->type;
1409 rmb->name = mb->name;
1410 rmb->table_idx = &mb->table_idx;
1411 rmb->init_locals = mb->init_locals;
1412 rmb->skip_visibility = FALSE;
1413 rmb->return_modreq = mb->return_modreq;
1414 rmb->return_modopt = mb->return_modopt;
1415 rmb->param_modreq = mb->param_modreq;
1416 rmb->param_modopt = mb->param_modopt;
1417 rmb->permissions = mb->permissions;
1418 rmb->mhandle = mb->mhandle;
1423 rmb->charset = mb->charset;
1424 rmb->extra_flags = mb->extra_flags;
1425 rmb->native_cc = mb->native_cc;
1426 rmb->dllentry = mb->dllentry;
1432 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1434 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1436 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1438 rmb->ilgen = mb->ilgen;
1439 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1440 rmb->parameters = mb->parameters;
1441 rmb->generic_params = NULL;
1442 rmb->generic_container = NULL;
1443 rmb->opt_types = NULL;
1444 rmb->pinfo = mb->pinfo;
1445 rmb->attrs = mb->attrs;
1446 rmb->iattrs = mb->iattrs;
1447 rmb->call_conv = mb->call_conv;
1449 rmb->type = mb->type;
1450 rmb->name = mono_string_new (mono_domain_get (), name);
1451 rmb->table_idx = &mb->table_idx;
1452 rmb->init_locals = mb->init_locals;
1453 rmb->skip_visibility = FALSE;
1454 rmb->return_modreq = NULL;
1455 rmb->return_modopt = NULL;
1456 rmb->param_modreq = mb->param_modreq;
1457 rmb->param_modopt = mb->param_modopt;
1458 rmb->permissions = mb->permissions;
1459 rmb->mhandle = mb->mhandle;
1464 #ifndef DISABLE_REFLECTION_EMIT
1466 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1468 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1470 rmb->ilgen = mb->ilgen;
1471 rmb->rtype = mb->rtype;
1472 rmb->parameters = mb->parameters;
1473 rmb->generic_params = NULL;
1474 rmb->generic_container = NULL;
1475 rmb->opt_types = NULL;
1477 rmb->attrs = mb->attrs;
1479 rmb->call_conv = mb->call_conv;
1481 rmb->type = (MonoObject *) mb->owner;
1482 rmb->name = mb->name;
1483 rmb->table_idx = NULL;
1484 rmb->init_locals = mb->init_locals;
1485 rmb->skip_visibility = mb->skip_visibility;
1486 rmb->return_modreq = NULL;
1487 rmb->return_modopt = NULL;
1488 rmb->param_modreq = NULL;
1489 rmb->param_modopt = NULL;
1490 rmb->permissions = NULL;
1491 rmb->mhandle = mb->mhandle;
1498 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1500 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1501 MonoDynamicTable *table;
1505 if (!mb->override_method)
1508 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1510 alloc_table (table, table->rows);
1511 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1512 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1513 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1515 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1516 switch (mono_metadata_token_table (tok)) {
1517 case MONO_TABLE_MEMBERREF:
1518 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1520 case MONO_TABLE_METHOD:
1521 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1524 g_assert_not_reached ();
1526 values [MONO_METHODIMPL_DECLARATION] = tok;
1530 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1532 MonoDynamicTable *table;
1534 ReflectionMethodBuilder rmb;
1537 reflection_methodbuilder_from_method_builder (&rmb, mb);
1539 mono_image_basic_method (&rmb, assembly);
1540 mb->table_idx = *rmb.table_idx;
1542 if (mb->dll) { /* It's a P/Invoke method */
1544 /* map CharSet values to on-disk values */
1545 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1546 int extra_flags = mb->extra_flags;
1547 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1549 alloc_table (table, table->rows);
1550 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1552 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1553 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1555 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1557 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1558 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1559 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1560 table = &assembly->tables [MONO_TABLE_MODULEREF];
1562 alloc_table (table, table->rows);
1563 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1564 values [MONO_IMPLMAP_SCOPE] = table->rows;
1568 if (mb->generic_params) {
1569 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1570 table->rows += mono_array_length (mb->generic_params);
1571 alloc_table (table, table->rows);
1572 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1573 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1575 mono_image_get_generic_param_info (
1576 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1583 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1585 ReflectionMethodBuilder rmb;
1587 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1589 mono_image_basic_method (&rmb, assembly);
1590 mb->table_idx = *rmb.table_idx;
1594 type_get_fully_qualified_name (MonoType *type)
1596 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1600 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1604 klass = mono_class_from_mono_type (type);
1606 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1607 ta = klass->image->assembly;
1608 if (ta->dynamic || (ta == ass)) {
1609 if (klass->generic_class || klass->generic_container)
1610 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1611 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1613 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1616 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1619 #ifndef DISABLE_REFLECTION_EMIT
1620 /*field_image is the image to which the eventual custom mods have been encoded against*/
1622 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1625 guint32 idx, i, token;
1627 if (!assembly->save)
1630 sigbuffer_init (&buf, 32);
1632 sigbuffer_add_value (&buf, 0x06);
1633 /* encode custom attributes before the type */
1634 if (type->num_mods) {
1635 for (i = 0; i < type->num_mods; ++i) {
1637 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1639 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1641 token = type->modifiers [i].token;
1644 if (type->modifiers [i].required)
1645 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1647 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1649 sigbuffer_add_value (&buf, token);
1652 encode_type (assembly, type, &buf);
1653 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1654 sigbuffer_free (&buf);
1660 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1665 sigbuffer_init (&buf, 32);
1667 sigbuffer_add_value (&buf, 0x06);
1668 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1669 /* encode custom attributes before the type */
1670 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1671 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1672 sigbuffer_free (&buf);
1677 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1678 char blob_size [64];
1679 char *b = blob_size;
1682 guint32 idx = 0, len = 0, dummy = 0;
1684 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1685 guint32 fpa_double [2];
1690 p = buf = g_malloc (64);
1692 *ret_type = MONO_TYPE_CLASS;
1694 box_val = (char*)&dummy;
1696 box_val = ((char*)val) + sizeof (MonoObject);
1697 *ret_type = val->vtable->klass->byval_arg.type;
1700 switch (*ret_type) {
1701 case MONO_TYPE_BOOLEAN:
1706 case MONO_TYPE_CHAR:
1723 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1724 fpa_p = (guint32*)box_val;
1725 fpa_double [0] = fpa_p [1];
1726 fpa_double [1] = fpa_p [0];
1727 box_val = (char*)fpa_double;
1731 case MONO_TYPE_VALUETYPE:
1732 if (val->vtable->klass->enumtype) {
1733 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1736 g_error ("we can't encode valuetypes");
1737 case MONO_TYPE_CLASS:
1739 case MONO_TYPE_STRING: {
1740 MonoString *str = (MonoString*)val;
1741 /* there is no signature */
1742 len = str->length * 2;
1743 mono_metadata_encode_value (len, b, &b);
1744 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1746 char *swapped = g_malloc (2 * mono_string_length (str));
1747 const char *p = (const char*)mono_string_chars (str);
1749 swap_with_size (swapped, p, 2, mono_string_length (str));
1750 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1754 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1760 case MONO_TYPE_GENERICINST:
1761 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1764 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1767 /* there is no signature */
1768 mono_metadata_encode_value (len, b, &b);
1769 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1770 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1771 swap_with_size (blob_size, box_val, len, 1);
1772 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1774 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1782 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1787 sigbuffer_init (&buf, 32);
1789 sigbuffer_add_value (&buf, minfo->type);
1791 switch (minfo->type) {
1792 case MONO_NATIVE_BYVALTSTR:
1793 case MONO_NATIVE_BYVALARRAY:
1794 sigbuffer_add_value (&buf, minfo->count);
1796 case MONO_NATIVE_LPARRAY:
1797 if (minfo->eltype || minfo->has_size) {
1798 sigbuffer_add_value (&buf, minfo->eltype);
1799 if (minfo->has_size) {
1800 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1801 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1803 /* LAMESPEC: ElemMult is undocumented */
1804 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1808 case MONO_NATIVE_SAFEARRAY:
1810 sigbuffer_add_value (&buf, minfo->eltype);
1812 case MONO_NATIVE_CUSTOM:
1814 str = mono_string_to_utf8 (minfo->guid);
1816 sigbuffer_add_value (&buf, len);
1817 sigbuffer_add_mem (&buf, str, len);
1820 sigbuffer_add_value (&buf, 0);
1822 /* native type name */
1823 sigbuffer_add_value (&buf, 0);
1824 /* custom marshaler type name */
1825 if (minfo->marshaltype || minfo->marshaltyperef) {
1826 if (minfo->marshaltyperef)
1827 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1829 str = mono_string_to_utf8 (minfo->marshaltype);
1831 sigbuffer_add_value (&buf, len);
1832 sigbuffer_add_mem (&buf, str, len);
1835 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1836 sigbuffer_add_value (&buf, 0);
1838 if (minfo->mcookie) {
1839 str = mono_string_to_utf8 (minfo->mcookie);
1841 sigbuffer_add_value (&buf, len);
1842 sigbuffer_add_mem (&buf, str, len);
1845 sigbuffer_add_value (&buf, 0);
1851 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1852 sigbuffer_free (&buf);
1857 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1859 MonoDynamicTable *table;
1862 /* maybe this fixup should be done in the C# code */
1863 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1864 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1865 table = &assembly->tables [MONO_TABLE_FIELD];
1866 fb->table_idx = table->next_idx ++;
1867 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1868 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1869 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1870 values [MONO_FIELD_FLAGS] = fb->attrs;
1871 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1873 if (fb->offset != -1) {
1874 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1876 alloc_table (table, table->rows);
1877 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1878 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1879 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1881 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1882 guint32 field_type = 0;
1883 table = &assembly->tables [MONO_TABLE_CONSTANT];
1885 alloc_table (table, table->rows);
1886 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1887 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1888 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1889 values [MONO_CONSTANT_TYPE] = field_type;
1890 values [MONO_CONSTANT_PADDING] = 0;
1892 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1894 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1896 alloc_table (table, table->rows);
1897 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1898 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1900 * We store it in the code section because it's simpler for now.
1903 if (mono_array_length (fb->rva_data) >= 10)
1904 stream_data_align (&assembly->code);
1905 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1907 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1908 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1910 if (fb->marshal_info) {
1911 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1913 alloc_table (table, table->rows);
1914 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1915 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1916 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1921 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1924 guint32 nparams = 0;
1925 MonoReflectionMethodBuilder *mb = fb->get_method;
1926 MonoReflectionMethodBuilder *smb = fb->set_method;
1929 if (mb && mb->parameters)
1930 nparams = mono_array_length (mb->parameters);
1931 if (!mb && smb && smb->parameters)
1932 nparams = mono_array_length (smb->parameters) - 1;
1933 sigbuffer_init (&buf, 32);
1934 sigbuffer_add_byte (&buf, 0x08);
1935 sigbuffer_add_value (&buf, nparams);
1937 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1938 for (i = 0; i < nparams; ++i) {
1939 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1940 encode_reflection_type (assembly, pt, &buf);
1942 } else if (smb && smb->parameters) {
1943 /* the property type is the last param */
1944 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1945 for (i = 0; i < nparams; ++i) {
1946 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1947 encode_reflection_type (assembly, pt, &buf);
1950 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1953 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1954 sigbuffer_free (&buf);
1959 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1961 MonoDynamicTable *table;
1963 guint num_methods = 0;
1967 * we need to set things in the following tables:
1968 * PROPERTYMAP (info already filled in _get_type_info ())
1969 * PROPERTY (rows already preallocated in _get_type_info ())
1970 * METHOD (method info already done with the generic method code)
1973 table = &assembly->tables [MONO_TABLE_PROPERTY];
1974 pb->table_idx = table->next_idx ++;
1975 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1976 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1977 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1978 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1980 /* FIXME: we still don't handle 'other' methods */
1981 if (pb->get_method) num_methods ++;
1982 if (pb->set_method) num_methods ++;
1984 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1985 table->rows += num_methods;
1986 alloc_table (table, table->rows);
1988 if (pb->get_method) {
1989 semaidx = table->next_idx ++;
1990 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1991 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1992 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1993 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1995 if (pb->set_method) {
1996 semaidx = table->next_idx ++;
1997 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1998 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1999 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2000 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2005 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2007 MonoDynamicTable *table;
2009 guint num_methods = 0;
2013 * we need to set things in the following tables:
2014 * EVENTMAP (info already filled in _get_type_info ())
2015 * EVENT (rows already preallocated in _get_type_info ())
2016 * METHOD (method info already done with the generic method code)
2019 table = &assembly->tables [MONO_TABLE_EVENT];
2020 eb->table_idx = table->next_idx ++;
2021 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2022 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2023 values [MONO_EVENT_FLAGS] = eb->attrs;
2024 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2027 * FIXME: we still don't handle 'other' methods
2029 if (eb->add_method) num_methods ++;
2030 if (eb->remove_method) num_methods ++;
2031 if (eb->raise_method) num_methods ++;
2033 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2034 table->rows += num_methods;
2035 alloc_table (table, table->rows);
2037 if (eb->add_method) {
2038 semaidx = table->next_idx ++;
2039 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2040 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2041 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2042 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2044 if (eb->remove_method) {
2045 semaidx = table->next_idx ++;
2046 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2047 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2048 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2049 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2051 if (eb->raise_method) {
2052 semaidx = table->next_idx ++;
2053 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2054 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2055 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2056 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2061 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2063 MonoDynamicTable *table;
2064 guint32 num_constraints, i;
2068 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2069 num_constraints = gparam->iface_constraints ?
2070 mono_array_length (gparam->iface_constraints) : 0;
2071 table->rows += num_constraints;
2072 if (gparam->base_type)
2074 alloc_table (table, table->rows);
2076 if (gparam->base_type) {
2077 table_idx = table->next_idx ++;
2078 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2080 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2081 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2082 assembly, mono_reflection_type_get_handle (gparam->base_type));
2085 for (i = 0; i < num_constraints; i++) {
2086 MonoReflectionType *constraint = mono_array_get (
2087 gparam->iface_constraints, gpointer, i);
2089 table_idx = table->next_idx ++;
2090 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2092 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2093 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2094 assembly, mono_reflection_type_get_handle (constraint));
2099 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2101 GenericParamTableEntry *entry;
2104 * The GenericParam table must be sorted according to the `owner' field.
2105 * We need to do this sorting prior to writing the GenericParamConstraint
2106 * table, since we have to use the final GenericParam table indices there
2107 * and they must also be sorted.
2110 entry = g_new0 (GenericParamTableEntry, 1);
2111 entry->owner = owner;
2112 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2113 MOVING_GC_REGISTER (&entry->gparam);
2114 entry->gparam = gparam;
2116 g_ptr_array_add (assembly->gen_params, entry);
2120 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2122 MonoDynamicTable *table;
2123 MonoGenericParam *param;
2127 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2128 table_idx = table->next_idx ++;
2129 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2131 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2133 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2134 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2135 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2136 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2138 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2140 encode_constraints (entry->gparam, table_idx, assembly);
2144 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2146 MonoDynamicTable *table;
2149 guint32 cols [MONO_ASSEMBLY_SIZE];
2153 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2156 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2157 table = &assembly->tables [MONO_TABLE_MODULEREF];
2158 token = table->next_idx ++;
2160 alloc_table (table, table->rows);
2161 values = table->values + token * MONO_MODULEREF_SIZE;
2162 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2164 token <<= MONO_RESOLTION_SCOPE_BITS;
2165 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2166 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2171 if (image->assembly->dynamic)
2173 memset (cols, 0, sizeof (cols));
2175 /* image->assembly->image is the manifest module */
2176 image = image->assembly->image;
2177 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2180 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2181 token = table->next_idx ++;
2183 alloc_table (table, table->rows);
2184 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2185 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2186 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2187 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2188 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2189 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2190 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2191 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2192 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2194 if (strcmp ("", image->assembly->aname.culture)) {
2195 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2196 image->assembly->aname.culture);
2199 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2200 guchar pubtoken [9];
2202 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2203 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2205 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2207 token <<= MONO_RESOLTION_SCOPE_BITS;
2208 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2209 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2214 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2216 MonoDynamicTable *table;
2221 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2224 sigbuffer_init (&buf, 32);
2225 switch (type->type) {
2226 case MONO_TYPE_FNPTR:
2228 case MONO_TYPE_SZARRAY:
2229 case MONO_TYPE_ARRAY:
2231 case MONO_TYPE_MVAR:
2232 case MONO_TYPE_GENERICINST:
2233 encode_type (assembly, type, &buf);
2235 case MONO_TYPE_CLASS:
2236 case MONO_TYPE_VALUETYPE: {
2237 MonoClass *k = mono_class_from_mono_type (type);
2238 if (!k || !k->generic_container) {
2239 sigbuffer_free (&buf);
2242 encode_type (assembly, type, &buf);
2246 sigbuffer_free (&buf);
2250 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2251 if (assembly->save) {
2252 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2253 alloc_table (table, table->rows + 1);
2254 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2255 values [MONO_TYPESPEC_SIGNATURE] = token;
2257 sigbuffer_free (&buf);
2259 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2260 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2266 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2268 MonoDynamicTable *table;
2270 guint32 token, scope, enclosing;
2273 /* if the type requires a typespec, we must try that first*/
2274 if (try_typespec && (token = create_typespec (assembly, type)))
2276 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2279 klass = mono_class_from_mono_type (type);
2281 klass = mono_class_from_mono_type (type);
2284 * If it's in the same module and not a generic type parameter:
2286 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2287 (type->type != MONO_TYPE_MVAR)) {
2288 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2289 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2290 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2294 if (klass->nested_in) {
2295 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2296 /* get the typeref idx of the enclosing type */
2297 enclosing >>= MONO_TYPEDEFORREF_BITS;
2298 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2300 scope = resolution_scope_from_image (assembly, klass->image);
2302 table = &assembly->tables [MONO_TABLE_TYPEREF];
2303 if (assembly->save) {
2304 alloc_table (table, table->rows + 1);
2305 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2306 values [MONO_TYPEREF_SCOPE] = scope;
2307 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2308 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2310 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2311 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2313 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2318 * Despite the name, we handle also TypeSpec (with the above helper).
2321 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2323 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2326 #ifndef DISABLE_REFLECTION_EMIT
2328 * Insert a memberef row into the metadata: the token that point to the memberref
2329 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2330 * mono_image_get_fieldref_token()).
2331 * The sig param is an index to an already built signature.
2334 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2336 MonoDynamicTable *table;
2338 guint32 token, pclass;
2341 parent = mono_image_typedef_or_ref (assembly, type);
2342 switch (parent & MONO_TYPEDEFORREF_MASK) {
2343 case MONO_TYPEDEFORREF_TYPEREF:
2344 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2346 case MONO_TYPEDEFORREF_TYPESPEC:
2347 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2349 case MONO_TYPEDEFORREF_TYPEDEF:
2350 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2353 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2356 /* extract the index */
2357 parent >>= MONO_TYPEDEFORREF_BITS;
2359 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2361 if (assembly->save) {
2362 alloc_table (table, table->rows + 1);
2363 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2364 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2365 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2366 values [MONO_MEMBERREF_SIGNATURE] = sig;
2369 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2376 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2379 MonoMethodSignature *sig;
2381 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2383 if (create_typespec) {
2384 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2389 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2390 if (token && !create_typespec)
2393 g_assert (!method->is_inflated);
2396 * A methodref signature can't contain an unmanaged calling convention.
2398 sig = mono_metadata_signature_dup (mono_method_signature (method));
2399 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2400 sig->call_convention = MONO_CALL_DEFAULT;
2401 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2402 method->name, method_encode_signature (assembly, sig));
2404 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2407 if (create_typespec) {
2408 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2409 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2410 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2412 if (assembly->save) {
2415 alloc_table (table, table->rows + 1);
2416 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2417 values [MONO_METHODSPEC_METHOD] = token;
2418 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2421 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2423 /*methodspec and memberef tokens are diferent, */
2424 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2431 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2434 ReflectionMethodBuilder rmb;
2437 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2441 name = mono_string_to_utf8 (method->name);
2442 reflection_methodbuilder_from_method_builder (&rmb, method);
2445 * A methodref signature can't contain an unmanaged calling convention.
2446 * Since some flags are encoded as part of call_conv, we need to check against it.
2448 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2449 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2450 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2451 name, method_builder_encode_signature (assembly, &rmb));
2454 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2459 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2460 const gchar *name, guint32 sig)
2462 MonoDynamicTable *table;
2466 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2468 if (assembly->save) {
2469 alloc_table (table, table->rows + 1);
2470 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2471 values [MONO_MEMBERREF_CLASS] = original;
2472 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2473 values [MONO_MEMBERREF_SIGNATURE] = sig;
2476 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2483 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2487 guint32 nparams = mono_array_length (mb->generic_params);
2490 if (!assembly->save)
2493 sigbuffer_init (&buf, 32);
2495 sigbuffer_add_value (&buf, 0xa);
2496 sigbuffer_add_value (&buf, nparams);
2498 for (i = 0; i < nparams; i++) {
2499 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2500 sigbuffer_add_value (&buf, i);
2503 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2504 sigbuffer_free (&buf);
2509 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2511 MonoDynamicTable *table;
2513 guint32 token, mtoken = 0;
2515 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2519 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2521 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2522 switch (mono_metadata_token_table (mtoken)) {
2523 case MONO_TABLE_MEMBERREF:
2524 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2526 case MONO_TABLE_METHOD:
2527 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2530 g_assert_not_reached ();
2533 if (assembly->save) {
2534 alloc_table (table, table->rows + 1);
2535 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2536 values [MONO_METHODSPEC_METHOD] = mtoken;
2537 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2540 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2543 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2548 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2552 if (mb->generic_params && create_methodspec)
2553 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2555 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2559 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2560 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2565 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2568 ReflectionMethodBuilder rmb;
2571 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2575 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2577 name = mono_string_to_utf8 (rmb.name);
2578 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2579 name, method_builder_encode_signature (assembly, &rmb));
2582 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2588 is_field_on_inst (MonoClassField *field)
2590 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2594 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2597 get_field_on_inst_generic_type (MonoClassField *field)
2599 MonoDynamicGenericClass *dgclass;
2602 g_assert (is_field_on_inst (field));
2604 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2605 field_index = field - dgclass->fields;
2607 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2608 return dgclass->field_generic_types [field_index];
2611 #ifndef DISABLE_REFLECTION_EMIT
2613 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2617 MonoClassField *field;
2619 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2622 g_assert (f->field->parent);
2625 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2626 int index = field - field->parent->fields;
2627 type = field->parent->generic_class->container_class->fields [index].type;
2629 if (is_field_on_inst (f->field))
2630 type = get_field_on_inst_generic_type (f->field);
2632 type = f->field->type;
2634 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2635 mono_field_get_name (f->field),
2636 fieldref_encode_signature (assembly, field->parent->image, type));
2637 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2642 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2646 MonoGenericClass *gclass;
2647 MonoDynamicGenericClass *dgclass;
2648 MonoReflectionFieldBuilder *fb = f->fb;
2652 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2655 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2656 klass = mono_class_from_mono_type (type);
2657 gclass = type->data.generic_class;
2658 g_assert (gclass->is_dynamic);
2659 dgclass = (MonoDynamicGenericClass *) gclass;
2661 name = mono_string_to_utf8 (fb->name);
2662 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2663 field_encode_signature (assembly, fb));
2665 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2670 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2674 MonoGenericClass *gclass;
2675 MonoDynamicGenericClass *dgclass;
2676 MonoReflectionCtorBuilder *cb = c->cb;
2677 ReflectionMethodBuilder rmb;
2681 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2683 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2686 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2687 klass = mono_class_from_mono_type (type);
2688 gclass = type->data.generic_class;
2689 g_assert (gclass->is_dynamic);
2690 dgclass = (MonoDynamicGenericClass *) gclass;
2692 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2694 name = mono_string_to_utf8 (rmb.name);
2696 sig = method_builder_encode_signature (assembly, &rmb);
2698 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2701 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2706 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2709 MonoGenericContext tmp_context;
2710 MonoType **type_argv;
2711 MonoGenericInst *ginst;
2712 MonoMethod *method, *inflated;
2715 method = inflate_method (m->inst, (MonoObject*)m->mb);
2717 klass = method->klass;
2719 if (method->is_inflated)
2720 method = ((MonoMethodInflated *) method)->declaring;
2722 count = mono_array_length (m->method_args);
2724 type_argv = g_new0 (MonoType *, count);
2725 for (i = 0; i < count; i++) {
2726 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2727 type_argv [i] = mono_reflection_type_get_handle (garg);
2729 ginst = mono_metadata_get_generic_inst (count, type_argv);
2732 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2733 tmp_context.method_inst = ginst;
2735 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2740 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2744 MonoGenericClass *gclass;
2745 MonoReflectionMethodBuilder *mb = m->mb;
2746 ReflectionMethodBuilder rmb;
2750 if (m->method_args) {
2751 MonoMethod *inflated;
2753 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2754 if (create_methodspec)
2755 token = mono_image_get_methodspec_token (assembly, inflated);
2757 token = mono_image_get_inflated_method_token (assembly, inflated);
2761 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2764 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2765 klass = mono_class_from_mono_type (type);
2766 gclass = type->data.generic_class;
2767 g_assert (gclass->is_dynamic);
2769 reflection_methodbuilder_from_method_builder (&rmb, mb);
2771 name = mono_string_to_utf8 (rmb.name);
2773 sig = method_builder_encode_signature (assembly, &rmb);
2775 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2778 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2783 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2787 guint32 nparams = context->method_inst->type_argc;
2790 if (!assembly->save)
2793 sigbuffer_init (&buf, 32);
2795 * FIXME: vararg, explicit_this, differenc call_conv values...
2797 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2798 sigbuffer_add_value (&buf, nparams);
2800 for (i = 0; i < nparams; i++)
2801 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2803 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2804 sigbuffer_free (&buf);
2809 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2811 MonoDynamicTable *table;
2813 guint32 token, mtoken = 0, sig;
2814 MonoMethodInflated *imethod;
2815 MonoMethod *declaring;
2817 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2819 g_assert (method->is_inflated);
2820 imethod = (MonoMethodInflated *) method;
2821 declaring = imethod->declaring;
2823 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2824 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2826 if (!mono_method_signature (declaring)->generic_param_count)
2829 switch (mono_metadata_token_table (mtoken)) {
2830 case MONO_TABLE_MEMBERREF:
2831 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2833 case MONO_TABLE_METHOD:
2834 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2837 g_assert_not_reached ();
2840 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2842 if (assembly->save) {
2843 alloc_table (table, table->rows + 1);
2844 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2845 values [MONO_METHODSPEC_METHOD] = mtoken;
2846 values [MONO_METHODSPEC_SIGNATURE] = sig;
2849 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2856 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2858 MonoMethodInflated *imethod;
2861 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2865 g_assert (method->is_inflated);
2866 imethod = (MonoMethodInflated *) method;
2868 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2869 token = method_encode_methodspec (assembly, method);
2871 guint32 sig = method_encode_signature (
2872 assembly, mono_method_signature (imethod->declaring));
2873 token = mono_image_get_memberref_token (
2874 assembly, &method->klass->byval_arg, method->name, sig);
2877 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2882 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2884 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2887 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2888 token = mono_image_get_memberref_token (
2889 assembly, &m->klass->byval_arg, m->name, sig);
2895 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2897 MonoDynamicTable *table;
2906 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2907 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2908 * Because of this, we must not insert it into the `typeref' hash table.
2910 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2911 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2915 sigbuffer_init (&buf, 32);
2917 g_assert (tb->generic_params);
2918 klass = mono_class_from_mono_type (type);
2920 if (tb->generic_container)
2921 mono_reflection_create_generic_class (tb);
2923 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2924 g_assert (klass->generic_container);
2925 sigbuffer_add_value (&buf, klass->byval_arg.type);
2926 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2928 count = mono_array_length (tb->generic_params);
2929 sigbuffer_add_value (&buf, count);
2930 for (i = 0; i < count; i++) {
2931 MonoReflectionGenericParam *gparam;
2933 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2935 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
2938 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2940 if (assembly->save) {
2941 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2942 alloc_table (table, table->rows + 1);
2943 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2944 values [MONO_TYPESPEC_SIGNATURE] = token;
2946 sigbuffer_free (&buf);
2948 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2949 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2955 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2958 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2960 int i, count, len, pos;
2965 count += mono_array_length (modreq);
2967 count += mono_array_length (modopt);
2970 return mono_metadata_type_dup (NULL, type);
2972 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
2974 memcpy (t, type, MONO_SIZEOF_TYPE);
2976 t->num_mods = count;
2979 for (i = 0; i < mono_array_length (modreq); ++i) {
2980 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
2981 t->modifiers [pos].required = 1;
2982 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2987 for (i = 0; i < mono_array_length (modopt); ++i) {
2988 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
2989 t->modifiers [pos].required = 0;
2990 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2999 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3001 MonoDynamicTable *table;
3003 MonoType *custom = NULL;
3005 guint32 token, pclass, parent, sig;
3008 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
3012 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3013 name = mono_string_to_utf8 (fb->name);
3015 /* fb->type does not include the custom modifiers */
3016 /* FIXME: We should do this in one place when a fieldbuilder is created */
3017 if (fb->modreq || fb->modopt) {
3018 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3019 sig = fieldref_encode_signature (assembly, NULL, custom);
3022 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3025 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3026 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3028 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3029 parent >>= MONO_TYPEDEFORREF_BITS;
3031 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3033 if (assembly->save) {
3034 alloc_table (table, table->rows + 1);
3035 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3036 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3037 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3038 values [MONO_MEMBERREF_SIGNATURE] = sig;
3041 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3043 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3049 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3056 if (!assembly->save)
3059 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3060 g_assert (helper->type == 2);
3062 if (helper->arguments)
3063 nargs = mono_array_length (helper->arguments);
3067 size = 10 + (nargs * 10);
3069 sigbuffer_init (&buf, 32);
3071 /* Encode calling convention */
3072 /* Change Any to Standard */
3073 if ((helper->call_conv & 0x03) == 0x03)
3074 helper->call_conv = 0x01;
3075 /* explicit_this implies has_this */
3076 if (helper->call_conv & 0x40)
3077 helper->call_conv &= 0x20;
3079 if (helper->call_conv == 0) { /* Unmanaged */
3080 idx = helper->unmanaged_call_conv - 1;
3083 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3084 if (helper->call_conv & 0x02) /* varargs */
3088 sigbuffer_add_byte (&buf, idx);
3089 sigbuffer_add_value (&buf, nargs);
3090 encode_reflection_type (assembly, helper->return_type, &buf);
3091 for (i = 0; i < nargs; ++i) {
3092 MonoArray *modreqs = NULL;
3093 MonoArray *modopts = NULL;
3094 MonoReflectionType *pt;
3096 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3097 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3098 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3099 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3101 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3102 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3103 encode_reflection_type (assembly, pt, &buf);
3105 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3106 sigbuffer_free (&buf);
3112 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3115 MonoDynamicTable *table;
3118 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3119 idx = table->next_idx ++;
3121 alloc_table (table, table->rows);
3122 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3124 values [MONO_STAND_ALONE_SIGNATURE] =
3125 mono_reflection_encode_sighelper (assembly, helper);
3131 reflection_cc_to_file (int call_conv) {
3132 switch (call_conv & 0x3) {
3134 case 1: return MONO_CALL_DEFAULT;
3135 case 2: return MONO_CALL_VARARG;
3137 g_assert_not_reached ();
3141 #endif /* !DISABLE_REFLECTION_EMIT */
3145 MonoMethodSignature *sig;
3150 #ifndef DISABLE_REFLECTION_EMIT
3152 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3157 MonoMethodSignature *sig;
3161 name = mono_string_to_utf8 (m->name);
3162 nparams = mono_array_length (m->parameters);
3163 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3165 sig->sentinelpos = -1;
3166 sig->call_convention = reflection_cc_to_file (m->call_conv);
3167 sig->param_count = nparams;
3168 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3169 mtype = mono_reflection_type_get_handle (m->parent);
3170 for (i = 0; i < nparams; ++i)
3171 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3173 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3175 if (strcmp (name, am->name) == 0 &&
3176 mono_metadata_type_equal (am->parent, mtype) &&
3177 mono_metadata_signature_equal (am->sig, sig)) {
3180 m->table_idx = am->token & 0xffffff;
3184 am = g_new0 (ArrayMethod, 1);
3188 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3189 method_encode_signature (assembly, sig));
3190 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3191 m->table_idx = am->token & 0xffffff;
3197 * Insert into the metadata tables all the info about the TypeBuilder tb.
3198 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3201 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3203 MonoDynamicTable *table;
3205 int i, is_object = 0, is_system = 0;
3208 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3209 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3210 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3211 n = mono_string_to_utf8 (tb->name);
3212 if (strcmp (n, "Object") == 0)
3214 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3216 n = mono_string_to_utf8 (tb->nspace);
3217 if (strcmp (n, "System") == 0)
3219 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3221 if (tb->parent && !(is_system && is_object) &&
3222 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3223 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3225 values [MONO_TYPEDEF_EXTENDS] = 0;
3227 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3228 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3231 * if we have explicitlayout or sequentiallayouts, output data in the
3232 * ClassLayout table.
3234 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3235 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3236 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3238 alloc_table (table, table->rows);
3239 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3240 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3241 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3242 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3245 /* handle interfaces */
3246 if (tb->interfaces) {
3247 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3249 table->rows += mono_array_length (tb->interfaces);
3250 alloc_table (table, table->rows);
3251 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3252 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3253 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3254 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3255 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3256 values += MONO_INTERFACEIMPL_SIZE;
3262 table = &assembly->tables [MONO_TABLE_FIELD];
3263 table->rows += tb->num_fields;
3264 alloc_table (table, table->rows);
3265 for (i = 0; i < tb->num_fields; ++i)
3266 mono_image_get_field_info (
3267 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3270 /* handle constructors */
3272 table = &assembly->tables [MONO_TABLE_METHOD];
3273 table->rows += mono_array_length (tb->ctors);
3274 alloc_table (table, table->rows);
3275 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3276 mono_image_get_ctor_info (domain,
3277 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3280 /* handle methods */
3282 table = &assembly->tables [MONO_TABLE_METHOD];
3283 table->rows += tb->num_methods;
3284 alloc_table (table, table->rows);
3285 for (i = 0; i < tb->num_methods; ++i)
3286 mono_image_get_method_info (
3287 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3290 /* Do the same with properties etc.. */
3291 if (tb->events && mono_array_length (tb->events)) {
3292 table = &assembly->tables [MONO_TABLE_EVENT];
3293 table->rows += mono_array_length (tb->events);
3294 alloc_table (table, table->rows);
3295 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3297 alloc_table (table, table->rows);
3298 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3299 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3300 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3301 for (i = 0; i < mono_array_length (tb->events); ++i)
3302 mono_image_get_event_info (
3303 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3305 if (tb->properties && mono_array_length (tb->properties)) {
3306 table = &assembly->tables [MONO_TABLE_PROPERTY];
3307 table->rows += mono_array_length (tb->properties);
3308 alloc_table (table, table->rows);
3309 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3311 alloc_table (table, table->rows);
3312 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3313 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3314 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3315 for (i = 0; i < mono_array_length (tb->properties); ++i)
3316 mono_image_get_property_info (
3317 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3320 /* handle generic parameters */
3321 if (tb->generic_params) {
3322 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3323 table->rows += mono_array_length (tb->generic_params);
3324 alloc_table (table, table->rows);
3325 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3326 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3328 mono_image_get_generic_param_info (
3329 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3333 mono_image_add_decl_security (assembly,
3334 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3337 MonoDynamicTable *ntable;
3339 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3340 ntable->rows += mono_array_length (tb->subtypes);
3341 alloc_table (ntable, ntable->rows);
3342 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3344 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3345 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3347 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3348 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3349 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3350 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3351 mono_string_to_utf8 (tb->name), tb->table_idx,
3352 ntable->next_idx, ntable->rows);*/
3353 values += MONO_NESTED_CLASS_SIZE;
3360 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3364 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3366 if (!type->subtypes)
3369 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3370 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3371 collect_types (types, subtype);
3376 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3378 if ((*type1)->table_idx < (*type2)->table_idx)
3381 if ((*type1)->table_idx > (*type2)->table_idx)
3388 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3393 for (i = 0; i < mono_array_length (pinfo); ++i) {
3394 MonoReflectionParamBuilder *pb;
3395 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3398 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3403 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3406 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3408 for (i = 0; i < tb->num_fields; ++i) {
3409 MonoReflectionFieldBuilder* fb;
3410 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3411 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3415 for (i = 0; i < mono_array_length (tb->events); ++i) {
3416 MonoReflectionEventBuilder* eb;
3417 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3418 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3421 if (tb->properties) {
3422 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3423 MonoReflectionPropertyBuilder* pb;
3424 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3425 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3429 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3430 MonoReflectionCtorBuilder* cb;
3431 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3432 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3433 params_add_cattrs (assembly, cb->pinfo);
3438 for (i = 0; i < tb->num_methods; ++i) {
3439 MonoReflectionMethodBuilder* mb;
3440 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3441 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3442 params_add_cattrs (assembly, mb->pinfo);
3447 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3448 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3453 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3457 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3459 if (moduleb->global_methods) {
3460 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3461 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3462 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3463 params_add_cattrs (assembly, mb->pinfo);
3467 if (moduleb->global_fields) {
3468 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3469 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3470 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3474 if (moduleb->types) {
3475 for (i = 0; i < moduleb->num_types; ++i)
3476 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3481 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3483 MonoDynamicTable *table;
3487 char *b = blob_size;
3490 table = &assembly->tables [MONO_TABLE_FILE];
3492 alloc_table (table, table->rows);
3493 values = table->values + table->next_idx * MONO_FILE_SIZE;
3494 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3495 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3496 if (module->image->dynamic) {
3497 /* This depends on the fact that the main module is emitted last */
3498 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3499 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3502 path = g_strdup (module->image->name);
3504 mono_sha1_get_digest_from_file (path, hash);
3507 mono_metadata_encode_value (20, b, &b);
3508 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3509 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3514 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3516 MonoDynamicTable *table;
3519 table = &assembly->tables [MONO_TABLE_MODULE];
3520 mb->table_idx = table->next_idx ++;
3521 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3522 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3525 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3526 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3527 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3528 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3532 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3533 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3535 MonoDynamicTable *table;
3539 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3540 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3543 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3545 alloc_table (table, table->rows);
3546 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3548 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3549 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3550 if (klass->nested_in)
3551 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3553 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3554 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3555 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3557 res = table->next_idx;
3561 /* Emit nested types */
3562 if (klass->ext && klass->ext->nested_classes) {
3565 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3566 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3573 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3574 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3579 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3581 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3583 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3584 parent_index, assembly);
3588 * We need to do this ourselves since klass->nested_classes is not set up.
3591 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3592 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3597 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3598 guint32 module_index, MonoDynamicImage *assembly)
3600 MonoImage *image = module->image;
3604 t = &image->tables [MONO_TABLE_TYPEDEF];
3606 for (i = 0; i < t->rows; ++i) {
3607 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3609 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3610 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3615 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3617 MonoDynamicTable *table;
3619 guint32 scope, idx, res, impl;
3620 gboolean forwarder = TRUE;
3622 if (klass->nested_in) {
3623 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3626 scope = resolution_scope_from_image (assembly, klass->image);
3627 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3628 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3629 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3632 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3635 alloc_table (table, table->rows);
3636 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3638 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3639 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3640 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3641 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3642 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3644 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3652 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3657 if (!assemblyb->type_forwarders)
3660 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3661 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3666 type = mono_reflection_type_get_handle (t);
3669 klass = mono_class_from_mono_type (type);
3671 add_exported_type (assemblyb, assembly, klass);
3675 #define align_pointer(base,p)\
3677 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3679 (p) += 4 - (__diff & 3);\
3683 compare_constants (const void *a, const void *b)
3685 const guint32 *a_values = a;
3686 const guint32 *b_values = b;
3687 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3691 compare_semantics (const void *a, const void *b)
3693 const guint32 *a_values = a;
3694 const guint32 *b_values = b;
3695 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3698 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3702 compare_custom_attrs (const void *a, const void *b)
3704 const guint32 *a_values = a;
3705 const guint32 *b_values = b;
3707 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3711 compare_field_marshal (const void *a, const void *b)
3713 const guint32 *a_values = a;
3714 const guint32 *b_values = b;
3716 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3720 compare_nested (const void *a, const void *b)
3722 const guint32 *a_values = a;
3723 const guint32 *b_values = b;
3725 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3729 compare_genericparam (const void *a, const void *b)
3731 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3732 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3734 if ((*b_entry)->owner == (*a_entry)->owner)
3736 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3737 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3739 return (*a_entry)->owner - (*b_entry)->owner;
3743 compare_declsecurity_attrs (const void *a, const void *b)
3745 const guint32 *a_values = a;
3746 const guint32 *b_values = b;
3748 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3752 compare_interface_impl (const void *a, const void *b)
3754 const guint32 *a_values = a;
3755 const guint32 *b_values = b;
3757 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3761 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3765 pad_heap (MonoDynamicStream *sh)
3767 if (sh->index & 3) {
3768 int sz = 4 - (sh->index & 3);
3769 memset (sh->data + sh->index, 0, sz);
3776 MonoDynamicStream *stream;
3780 * build_compressed_metadata() fills in the blob of data that represents the
3781 * raw metadata as it will be saved in the PE file. The five streams are output
3782 * and the metadata tables are comnpressed from the guint32 array representation,
3783 * to the compressed on-disk format.
3786 build_compressed_metadata (MonoDynamicImage *assembly)
3788 MonoDynamicTable *table;
3790 guint64 valid_mask = 0;
3791 guint64 sorted_mask;
3792 guint32 heapt_size = 0;
3793 guint32 meta_size = 256; /* allow for header and other stuff */
3794 guint32 table_offset;
3795 guint32 ntables = 0;
3801 struct StreamDesc stream_desc [5];
3803 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3804 for (i = 0; i < assembly->gen_params->len; i++){
3805 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3806 write_generic_param_entry (assembly, entry);
3809 stream_desc [0].name = "#~";
3810 stream_desc [0].stream = &assembly->tstream;
3811 stream_desc [1].name = "#Strings";
3812 stream_desc [1].stream = &assembly->sheap;
3813 stream_desc [2].name = "#US";
3814 stream_desc [2].stream = &assembly->us;
3815 stream_desc [3].name = "#Blob";
3816 stream_desc [3].stream = &assembly->blob;
3817 stream_desc [4].name = "#GUID";
3818 stream_desc [4].stream = &assembly->guid;
3820 /* tables that are sorted */
3821 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3822 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3823 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3824 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3825 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3826 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3827 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3829 /* Compute table sizes */
3830 /* the MonoImage has already been created in mono_image_basic_init() */
3831 meta = &assembly->image;
3833 /* sizes should be multiple of 4 */
3834 pad_heap (&assembly->blob);
3835 pad_heap (&assembly->guid);
3836 pad_heap (&assembly->sheap);
3837 pad_heap (&assembly->us);
3839 /* Setup the info used by compute_sizes () */
3840 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3841 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3842 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3844 meta_size += assembly->blob.index;
3845 meta_size += assembly->guid.index;
3846 meta_size += assembly->sheap.index;
3847 meta_size += assembly->us.index;
3849 for (i=0; i < MONO_TABLE_NUM; ++i)
3850 meta->tables [i].rows = assembly->tables [i].rows;
3852 for (i = 0; i < MONO_TABLE_NUM; i++){
3853 if (meta->tables [i].rows == 0)
3855 valid_mask |= (guint64)1 << i;
3857 meta->tables [i].row_size = mono_metadata_compute_size (
3858 meta, i, &meta->tables [i].size_bitfield);
3859 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3861 heapt_size += 24; /* #~ header size */
3862 heapt_size += ntables * 4;
3863 /* make multiple of 4 */
3866 meta_size += heapt_size;
3867 meta->raw_metadata = g_malloc0 (meta_size);
3868 p = (unsigned char*)meta->raw_metadata;
3869 /* the metadata signature */
3870 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3871 /* version numbers and 4 bytes reserved */
3872 int16val = (guint16*)p;
3873 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3874 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3876 /* version string */
3877 int32val = (guint32*)p;
3878 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3880 memcpy (p, meta->version, strlen (meta->version));
3881 p += GUINT32_FROM_LE (*int32val);
3882 align_pointer (meta->raw_metadata, p);
3883 int16val = (guint16*)p;
3884 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3885 *int16val = GUINT16_TO_LE (5); /* number of streams */
3889 * write the stream info.
3891 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3892 table_offset += 3; table_offset &= ~3;
3894 assembly->tstream.index = heapt_size;
3895 for (i = 0; i < 5; ++i) {
3896 int32val = (guint32*)p;
3897 stream_desc [i].stream->offset = table_offset;
3898 *int32val++ = GUINT32_TO_LE (table_offset);
3899 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3900 table_offset += GUINT32_FROM_LE (*int32val);
3901 table_offset += 3; table_offset &= ~3;
3903 strcpy ((char*)p, stream_desc [i].name);
3904 p += strlen (stream_desc [i].name) + 1;
3905 align_pointer (meta->raw_metadata, p);
3908 * now copy the data, the table stream header and contents goes first.
3910 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3911 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3912 int32val = (guint32*)p;
3913 *int32val = GUINT32_TO_LE (0); /* reserved */
3916 if (mono_framework_version () > 1) {
3917 *p++ = 2; /* version */
3920 *p++ = 1; /* version */
3924 if (meta->idx_string_wide)
3926 if (meta->idx_guid_wide)
3928 if (meta->idx_blob_wide)
3931 *p++ = 1; /* reserved */
3932 int64val = (guint64*)p;
3933 *int64val++ = GUINT64_TO_LE (valid_mask);
3934 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3936 int32val = (guint32*)p;
3937 for (i = 0; i < MONO_TABLE_NUM; i++){
3938 if (meta->tables [i].rows == 0)
3940 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3942 p = (unsigned char*)int32val;
3944 /* sort the tables that still need sorting */
3945 table = &assembly->tables [MONO_TABLE_CONSTANT];
3947 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3948 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3950 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3951 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3953 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3954 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3956 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3957 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3959 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3960 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3961 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3963 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3964 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3966 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3968 /* compress the tables */
3969 for (i = 0; i < MONO_TABLE_NUM; i++){
3972 guint32 bitfield = meta->tables [i].size_bitfield;
3973 if (!meta->tables [i].rows)
3975 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3976 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3977 meta->tables [i].base = (char*)p;
3978 for (row = 1; row <= meta->tables [i].rows; ++row) {
3979 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3980 for (col = 0; col < assembly->tables [i].columns; ++col) {
3981 switch (mono_metadata_table_size (bitfield, col)) {
3983 *p++ = values [col];
3986 *p++ = values [col] & 0xff;
3987 *p++ = (values [col] >> 8) & 0xff;
3990 *p++ = values [col] & 0xff;
3991 *p++ = (values [col] >> 8) & 0xff;
3992 *p++ = (values [col] >> 16) & 0xff;
3993 *p++ = (values [col] >> 24) & 0xff;
3996 g_assert_not_reached ();
4000 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4003 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4004 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4005 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4006 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4007 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4009 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4013 * Some tables in metadata need to be sorted according to some criteria, but
4014 * when methods and fields are first created with reflection, they may be assigned a token
4015 * that doesn't correspond to the final token they will get assigned after the sorting.
4016 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4017 * with the reflection objects that represent them. Once all the tables are set up, the
4018 * reflection objects will contains the correct table index. fixup_method() will fixup the
4019 * tokens for the method with ILGenerator @ilgen.
4022 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4024 guint32 code_idx = GPOINTER_TO_UINT (value);
4025 MonoReflectionILTokenInfo *iltoken;
4026 MonoReflectionFieldBuilder *field;
4027 MonoReflectionCtorBuilder *ctor;
4028 MonoReflectionMethodBuilder *method;
4029 MonoReflectionTypeBuilder *tb;
4030 MonoReflectionArrayMethod *am;
4032 unsigned char *target;
4034 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4035 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4036 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4037 switch (target [3]) {
4038 case MONO_TABLE_FIELD:
4039 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4040 field = (MonoReflectionFieldBuilder *)iltoken->member;
4041 idx = field->table_idx;
4042 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4043 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4044 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4046 g_assert_not_reached ();
4049 case MONO_TABLE_METHOD:
4050 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4051 method = (MonoReflectionMethodBuilder *)iltoken->member;
4052 idx = method->table_idx;
4053 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4054 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4055 idx = ctor->table_idx;
4056 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4057 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4058 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4059 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4061 g_assert_not_reached ();
4064 case MONO_TABLE_TYPEDEF:
4065 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4066 g_assert_not_reached ();
4067 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4068 idx = tb->table_idx;
4070 case MONO_TABLE_MEMBERREF:
4071 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4072 am = (MonoReflectionArrayMethod*)iltoken->member;
4073 idx = am->table_idx;
4074 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4075 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4076 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4077 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4078 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4079 g_assert (m->klass->generic_class || m->klass->generic_container);
4081 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4083 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4084 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4085 g_assert (is_field_on_inst (f));
4087 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4088 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4090 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4092 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4094 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4097 g_assert_not_reached ();
4100 case MONO_TABLE_METHODSPEC:
4101 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4102 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4103 g_assert (mono_method_signature (m)->generic_param_count);
4105 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4107 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4110 g_assert_not_reached ();
4114 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4116 target [0] = idx & 0xff;
4117 target [1] = (idx >> 8) & 0xff;
4118 target [2] = (idx >> 16) & 0xff;
4125 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4126 * value is not known when the table is emitted.
4129 fixup_cattrs (MonoDynamicImage *assembly)
4131 MonoDynamicTable *table;
4133 guint32 type, i, idx, token;
4136 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4138 for (i = 0; i < table->rows; ++i) {
4139 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4141 type = values [MONO_CUSTOM_ATTR_TYPE];
4142 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4143 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4144 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4145 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4148 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4149 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4150 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4151 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4158 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4160 MonoDynamicTable *table;
4163 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4165 alloc_table (table, table->rows);
4166 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4167 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4168 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4169 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4170 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4175 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4177 MonoDynamicTable *table;
4181 char *b = blob_size;
4183 guint32 idx, offset;
4185 if (rsrc->filename) {
4186 name = mono_string_to_utf8 (rsrc->filename);
4187 sname = g_path_get_basename (name);
4189 table = &assembly->tables [MONO_TABLE_FILE];
4191 alloc_table (table, table->rows);
4192 values = table->values + table->next_idx * MONO_FILE_SIZE;
4193 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4194 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4197 mono_sha1_get_digest_from_file (name, hash);
4198 mono_metadata_encode_value (20, b, &b);
4199 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4200 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4202 idx = table->next_idx++;
4204 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4210 data = mono_array_addr (rsrc->data, char, 0);
4211 len = mono_array_length (rsrc->data);
4217 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4218 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4219 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4220 mono_image_add_stream_data (&assembly->resources, data, len);
4224 * The entry should be emitted into the MANIFESTRESOURCE table of
4225 * the main module, but that needs to reference the FILE table
4226 * which isn't emitted yet.
4233 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4237 set_version_from_string (MonoString *version, guint32 *values)
4239 gchar *ver, *p, *str;
4242 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4243 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4244 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4245 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4248 ver = str = mono_string_to_utf8 (version);
4249 for (i = 0; i < 4; ++i) {
4250 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4256 /* handle Revision and Build */
4266 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4270 char *b = blob_size;
4275 len = mono_array_length (pkey);
4276 mono_metadata_encode_value (len, b, &b);
4277 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4278 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4280 assembly->public_key = g_malloc (len);
4281 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4282 assembly->public_key_len = len;
4284 /* Special case: check for ECMA key (16 bytes) */
4285 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4286 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4287 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4288 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4289 /* minimum key size (in 2.0) is 384 bits */
4290 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4292 /* FIXME - verifier */
4293 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4294 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4296 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4302 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4304 MonoDynamicTable *table;
4305 MonoDynamicImage *assembly;
4306 MonoReflectionAssemblyBuilder *assemblyb;
4310 guint32 module_index;
4312 assemblyb = moduleb->assemblyb;
4313 assembly = moduleb->dynamic_image;
4314 domain = mono_object_domain (assemblyb);
4316 /* Emit ASSEMBLY table */
4317 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4318 alloc_table (table, 1);
4319 values = table->values + MONO_ASSEMBLY_SIZE;
4320 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4321 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4322 if (assemblyb->culture) {
4323 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4325 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4327 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4328 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4329 set_version_from_string (assemblyb->version, values);
4331 /* Emit FILE + EXPORTED_TYPE table */
4333 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4335 MonoReflectionModuleBuilder *file_module =
4336 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4337 if (file_module != moduleb) {
4338 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4340 if (file_module->types) {
4341 for (j = 0; j < file_module->num_types; ++j) {
4342 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4343 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4348 if (assemblyb->loaded_modules) {
4349 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4350 MonoReflectionModule *file_module =
4351 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4352 mono_image_fill_file_table (domain, file_module, assembly);
4354 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4357 if (assemblyb->type_forwarders)
4358 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4360 /* Emit MANIFESTRESOURCE table */
4362 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4364 MonoReflectionModuleBuilder *file_module =
4365 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4366 /* The table for the main module is emitted later */
4367 if (file_module != moduleb) {
4369 if (file_module->resources) {
4370 int len = mono_array_length (file_module->resources);
4371 for (j = 0; j < len; ++j) {
4372 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4373 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4380 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4383 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4384 * for the modulebuilder @moduleb.
4385 * At the end of the process, method and field tokens are fixed up and the
4386 * on-disk compressed metadata representation is created.
4389 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4391 MonoDynamicTable *table;
4392 MonoDynamicImage *assembly;
4393 MonoReflectionAssemblyBuilder *assemblyb;
4399 assemblyb = moduleb->assemblyb;
4400 assembly = moduleb->dynamic_image;
4401 domain = mono_object_domain (assemblyb);
4403 if (assembly->text_rva)
4406 assembly->text_rva = START_TEXT_RVA;
4408 if (moduleb->is_main) {
4409 mono_image_emit_manifest (moduleb);
4412 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4413 table->rows = 1; /* .<Module> */
4415 alloc_table (table, table->rows);
4417 * Set the first entry.
4419 values = table->values + table->columns;
4420 values [MONO_TYPEDEF_FLAGS] = 0;
4421 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4422 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4423 values [MONO_TYPEDEF_EXTENDS] = 0;
4424 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4425 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4428 * handle global methods
4429 * FIXME: test what to do when global methods are defined in multiple modules.
4431 if (moduleb->global_methods) {
4432 table = &assembly->tables [MONO_TABLE_METHOD];
4433 table->rows += mono_array_length (moduleb->global_methods);
4434 alloc_table (table, table->rows);
4435 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4436 mono_image_get_method_info (
4437 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4439 if (moduleb->global_fields) {
4440 table = &assembly->tables [MONO_TABLE_FIELD];
4441 table->rows += mono_array_length (moduleb->global_fields);
4442 alloc_table (table, table->rows);
4443 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4444 mono_image_get_field_info (
4445 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4448 table = &assembly->tables [MONO_TABLE_MODULE];
4449 alloc_table (table, 1);
4450 mono_image_fill_module_table (domain, moduleb, assembly);
4452 /* Collect all types into a list sorted by their table_idx */
4453 types = g_ptr_array_new ();
4456 for (i = 0; i < moduleb->num_types; ++i) {
4457 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4458 collect_types (types, type);
4461 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4462 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4463 table->rows += types->len;
4464 alloc_table (table, table->rows);
4467 * Emit type names + namespaces at one place inside the string heap,
4468 * so load_class_names () needs to touch fewer pages.
4470 for (i = 0; i < types->len; ++i) {
4471 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4472 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4474 for (i = 0; i < types->len; ++i) {
4475 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4476 string_heap_insert_mstring (&assembly->sheap, tb->name);
4479 for (i = 0; i < types->len; ++i) {
4480 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4481 mono_image_get_type_info (domain, type, assembly);
4485 * table->rows is already set above and in mono_image_fill_module_table.
4487 /* add all the custom attributes at the end, once all the indexes are stable */
4488 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4490 /* CAS assembly permissions */
4491 if (assemblyb->permissions_minimum)
4492 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4493 if (assemblyb->permissions_optional)
4494 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4495 if (assemblyb->permissions_refused)
4496 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4498 module_add_cattrs (assembly, moduleb);
4501 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4503 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4504 * the final tokens and don't need another fixup pass. */
4506 if (moduleb->global_methods) {
4507 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4508 MonoReflectionMethodBuilder *mb = mono_array_get (
4509 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4510 mono_image_add_methodimpl (assembly, mb);
4514 for (i = 0; i < types->len; ++i) {
4515 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4516 if (type->methods) {
4517 for (j = 0; j < type->num_methods; ++j) {
4518 MonoReflectionMethodBuilder *mb = mono_array_get (
4519 type->methods, MonoReflectionMethodBuilder*, j);
4521 mono_image_add_methodimpl (assembly, mb);
4526 g_ptr_array_free (types, TRUE);
4528 fixup_cattrs (assembly);
4531 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4534 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4536 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4539 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4543 guint32 import_lookup_table;
4547 guint32 import_address_table_rva;
4555 #ifndef DISABLE_REFLECTION_EMIT
4558 * mono_image_insert_string:
4559 * @module: module builder object
4562 * Insert @str into the user string stream of @module.
4565 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4567 MonoDynamicImage *assembly;
4572 MONO_ARCH_SAVE_REGS;
4574 if (!module->dynamic_image)
4575 mono_image_module_basic_init (module);
4577 assembly = module->dynamic_image;
4579 if (assembly->save) {
4580 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4581 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4582 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4584 char *swapped = g_malloc (2 * mono_string_length (str));
4585 const char *p = (const char*)mono_string_chars (str);
4587 swap_with_size (swapped, p, 2, mono_string_length (str));
4588 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4592 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4594 mono_image_add_stream_data (&assembly->us, "", 1);
4596 idx = assembly->us.index ++;
4599 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4601 return MONO_TOKEN_STRING | idx;
4605 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4610 klass = obj->vtable->klass;
4611 if (strcmp (klass->name, "MonoMethod") == 0) {
4612 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4613 MonoMethodSignature *sig, *old;
4614 guint32 sig_token, parent;
4617 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4619 nargs = mono_array_length (opt_param_types);
4620 old = mono_method_signature (method);
4621 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4623 sig->hasthis = old->hasthis;
4624 sig->explicit_this = old->explicit_this;
4625 sig->call_convention = old->call_convention;
4626 sig->generic_param_count = old->generic_param_count;
4627 sig->param_count = old->param_count + nargs;
4628 sig->sentinelpos = old->param_count;
4629 sig->ret = old->ret;
4631 for (i = 0; i < old->param_count; i++)
4632 sig->params [i] = old->params [i];
4634 for (i = 0; i < nargs; i++) {
4635 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4636 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4639 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4640 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4641 parent >>= MONO_TYPEDEFORREF_BITS;
4643 parent <<= MONO_MEMBERREF_PARENT_BITS;
4644 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4646 sig_token = method_encode_signature (assembly, sig);
4647 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4648 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4649 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4650 ReflectionMethodBuilder rmb;
4651 guint32 parent, sig;
4654 reflection_methodbuilder_from_method_builder (&rmb, mb);
4655 rmb.opt_types = opt_param_types;
4657 sig = method_builder_encode_signature (assembly, &rmb);
4659 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4660 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4662 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4663 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4665 name = mono_string_to_utf8 (rmb.name);
4666 token = mono_image_get_varargs_method_token (
4667 assembly, parent, name, sig);
4670 g_error ("requested method token for %s\n", klass->name);
4677 * mono_image_create_token:
4678 * @assembly: a dynamic assembly
4680 * @register_token: Whenever to register the token in the assembly->tokens hash.
4682 * Get a token to insert in the IL code stream for the given MemberInfo.
4683 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4684 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4688 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4689 gboolean create_methodspec, gboolean register_token)
4694 klass = obj->vtable->klass;
4696 /* Check for user defined reflection objects */
4697 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4698 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4699 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4701 if (strcmp (klass->name, "MethodBuilder") == 0) {
4702 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4703 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4705 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4706 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4708 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4709 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4710 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4711 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4712 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4714 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4715 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4717 token = mono_image_get_ctorbuilder_token (assembly, mb);
4718 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4719 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4720 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4721 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4722 if (tb->generic_params) {
4723 token = mono_image_get_generic_field_token (assembly, fb);
4725 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4727 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4728 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4729 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4730 } else if (strcmp (klass->name, "MonoType") == 0) {
4731 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4732 MonoClass *mc = mono_class_from_mono_type (type);
4733 token = mono_metadata_token_from_dor (
4734 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4735 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4736 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4737 token = mono_metadata_token_from_dor (
4738 mono_image_typedef_or_ref (assembly, type));
4739 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4740 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4741 token = mono_metadata_token_from_dor (
4742 mono_image_typedef_or_ref (assembly, type));
4743 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4744 strcmp (klass->name, "MonoMethod") == 0 ||
4745 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4746 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4747 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4748 if (m->method->is_inflated) {
4749 if (create_methodspec)
4750 token = mono_image_get_methodspec_token (assembly, m->method);
4752 token = mono_image_get_inflated_method_token (assembly, m->method);
4753 } else if ((m->method->klass->image == &assembly->image) &&
4754 !m->method->klass->generic_class) {
4755 static guint32 method_table_idx = 0xffffff;
4756 if (m->method->klass->wastypebuilder) {
4757 /* we use the same token as the one that was assigned
4758 * to the Methodbuilder.
4759 * FIXME: do the equivalent for Fields.
4761 token = m->method->token;
4764 * Each token should have a unique index, but the indexes are
4765 * assigned by managed code, so we don't know about them. An
4766 * easy solution is to count backwards...
4768 method_table_idx --;
4769 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4772 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4774 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4775 } else if (strcmp (klass->name, "MonoField") == 0) {
4776 MonoReflectionField *f = (MonoReflectionField *)obj;
4777 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4778 static guint32 field_table_idx = 0xffffff;
4780 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4782 token = mono_image_get_fieldref_token (assembly, f);
4784 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4785 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4786 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4787 token = mono_image_get_array_token (assembly, m);
4788 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4789 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4790 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4791 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4792 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4793 token = mono_metadata_token_from_dor (
4794 mono_image_typedef_or_ref (assembly, type));
4795 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4796 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4797 token = mono_image_get_field_on_inst_token (assembly, f);
4798 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4799 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4800 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4801 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4802 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4803 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4804 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4805 MonoReflectionType *type = (MonoReflectionType *)obj;
4806 token = mono_metadata_token_from_dor (
4807 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4809 g_error ("requested token for %s\n", klass->name);
4813 mono_image_register_token (assembly, token, obj);
4819 * mono_image_register_token:
4821 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4822 * the Module.ResolveXXXToken () methods to work.
4825 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4827 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4829 /* There could be multiple MethodInfo objects with the same token */
4830 //g_assert (prev == obj);
4832 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4836 static MonoDynamicImage*
4837 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4839 static const guchar entrycode [16] = {0xff, 0x25, 0};
4840 MonoDynamicImage *image;
4843 const char *version;
4845 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4846 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4848 version = mono_get_runtime_info ()->runtime_version;
4851 image = GC_MALLOC (sizeof (MonoDynamicImage));
4853 image = g_new0 (MonoDynamicImage, 1);
4856 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4858 /*g_print ("created image %p\n", image);*/
4859 /* keep in sync with image.c */
4860 image->image.name = assembly_name;
4861 image->image.assembly_name = image->image.name; /* they may be different */
4862 image->image.module_name = module_name;
4863 image->image.version = g_strdup (version);
4864 image->image.md_version_major = 1;
4865 image->image.md_version_minor = 1;
4866 image->image.dynamic = TRUE;
4868 image->image.references = g_new0 (MonoAssembly*, 1);
4869 image->image.references [0] = NULL;
4871 mono_image_init (&image->image);
4873 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4874 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4875 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4876 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4877 image->handleref = g_hash_table_new (NULL, NULL);
4878 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4879 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4880 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4881 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4882 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4883 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4884 image->gen_params = g_ptr_array_new ();
4886 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4887 string_heap_init (&image->sheap);
4888 mono_image_add_stream_data (&image->us, "", 1);
4889 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4890 /* import tables... */
4891 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4892 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4893 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4894 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4895 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4896 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4897 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4898 stream_data_align (&image->code);
4900 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4902 for (i=0; i < MONO_TABLE_NUM; ++i) {
4903 image->tables [i].next_idx = 1;
4904 image->tables [i].columns = table_sizes [i];
4907 image->image.assembly = (MonoAssembly*)assembly;
4908 image->run = assembly->run;
4909 image->save = assembly->save;
4910 image->pe_kind = 0x1; /* ILOnly */
4911 image->machine = 0x14c; /* I386 */
4913 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4920 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4926 mono_dynamic_image_free (MonoDynamicImage *image)
4928 MonoDynamicImage *di = image;
4933 mono_g_hash_table_destroy (di->methodspec);
4935 g_hash_table_destroy (di->typespec);
4937 g_hash_table_destroy (di->typeref);
4939 g_hash_table_destroy (di->handleref);
4941 mono_g_hash_table_destroy (di->tokens);
4942 if (di->generic_def_objects)
4943 mono_g_hash_table_destroy (di->generic_def_objects);
4944 if (di->blob_cache) {
4945 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4946 g_hash_table_destroy (di->blob_cache);
4948 if (di->standalonesig_cache)
4949 g_hash_table_destroy (di->standalonesig_cache);
4950 for (list = di->array_methods; list; list = list->next) {
4951 ArrayMethod *am = (ArrayMethod *)list->data;
4956 g_list_free (di->array_methods);
4957 if (di->gen_params) {
4958 for (i = 0; i < di->gen_params->len; i++) {
4959 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4960 if (entry->gparam->type.type) {
4961 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4962 g_free ((char*)mono_generic_param_info (param)->name);
4965 mono_gc_deregister_root ((char*) &entry->gparam);
4968 g_ptr_array_free (di->gen_params, TRUE);
4970 if (di->token_fixups)
4971 mono_g_hash_table_destroy (di->token_fixups);
4972 if (di->method_to_table_idx)
4973 g_hash_table_destroy (di->method_to_table_idx);
4974 if (di->field_to_table_idx)
4975 g_hash_table_destroy (di->field_to_table_idx);
4976 if (di->method_aux_hash)
4977 g_hash_table_destroy (di->method_aux_hash);
4978 g_free (di->strong_name);
4979 g_free (di->win32_res);
4981 g_free (di->public_key);
4983 /*g_print ("string heap destroy for image %p\n", di);*/
4984 mono_dynamic_stream_reset (&di->sheap);
4985 mono_dynamic_stream_reset (&di->code);
4986 mono_dynamic_stream_reset (&di->resources);
4987 mono_dynamic_stream_reset (&di->us);
4988 mono_dynamic_stream_reset (&di->blob);
4989 mono_dynamic_stream_reset (&di->tstream);
4990 mono_dynamic_stream_reset (&di->guid);
4991 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4992 g_free (di->tables [i].values);
4996 #ifndef DISABLE_REFLECTION_EMIT
4999 * mono_image_basic_init:
5000 * @assembly: an assembly builder object
5002 * Create the MonoImage that represents the assembly builder and setup some
5003 * of the helper hash table and the basic metadata streams.
5006 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5008 MonoDynamicAssembly *assembly;
5009 MonoDynamicImage *image;
5010 MonoDomain *domain = mono_object_domain (assemblyb);
5012 MONO_ARCH_SAVE_REGS;
5014 if (assemblyb->dynamic_assembly)
5018 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5020 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5023 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5025 assembly->assembly.ref_count = 1;
5026 assembly->assembly.dynamic = TRUE;
5027 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5028 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5029 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5030 if (assemblyb->culture)
5031 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5033 assembly->assembly.aname.culture = g_strdup ("");
5035 if (assemblyb->version) {
5036 char *vstr = mono_string_to_utf8 (assemblyb->version);
5037 char **version = g_strsplit (vstr, ".", 4);
5038 char **parts = version;
5039 assembly->assembly.aname.major = atoi (*parts++);
5040 assembly->assembly.aname.minor = atoi (*parts++);
5041 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5042 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5044 g_strfreev (version);
5047 assembly->assembly.aname.major = 0;
5048 assembly->assembly.aname.minor = 0;
5049 assembly->assembly.aname.build = 0;
5050 assembly->assembly.aname.revision = 0;
5053 assembly->run = assemblyb->access != 2;
5054 assembly->save = assemblyb->access != 1;
5056 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5057 image->initial_image = TRUE;
5058 assembly->assembly.aname.name = image->image.name;
5059 assembly->assembly.image = &image->image;
5060 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5061 /* -1 to correct for the trailing NULL byte */
5062 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5063 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5065 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5068 mono_domain_assemblies_lock (domain);
5069 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5070 mono_domain_assemblies_unlock (domain);
5072 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5074 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5076 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5079 #endif /* !DISABLE_REFLECTION_EMIT */
5081 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5084 calc_section_size (MonoDynamicImage *assembly)
5088 /* alignment constraints */
5089 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5090 g_assert ((assembly->code.index % 4) == 0);
5091 assembly->meta_size += 3;
5092 assembly->meta_size &= ~3;
5093 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5094 g_assert ((assembly->resources.index % 4) == 0);
5096 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5097 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5100 if (assembly->win32_res) {
5101 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5103 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5104 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5108 assembly->sections [MONO_SECTION_RELOC].size = 12;
5109 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5119 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5123 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5125 ResTreeNode *t1 = (ResTreeNode*)a;
5126 ResTreeNode *t2 = (ResTreeNode*)b;
5128 return t1->id - t2->id;
5132 * resource_tree_create:
5134 * Organize the resources into a resource tree.
5136 static ResTreeNode *
5137 resource_tree_create (MonoArray *win32_resources)
5139 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5143 tree = g_new0 (ResTreeNode, 1);
5145 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5146 MonoReflectionWin32Resource *win32_res =
5147 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5151 /* FIXME: BUG: this stores managed references in unmanaged memory */
5152 lang_node = g_new0 (ResTreeNode, 1);
5153 lang_node->id = win32_res->lang_id;
5154 lang_node->win32_res = win32_res;
5156 /* Create type node if neccesary */
5158 for (l = tree->children; l; l = l->next)
5159 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5160 type_node = (ResTreeNode*)l->data;
5165 type_node = g_new0 (ResTreeNode, 1);
5166 type_node->id = win32_res->res_type;
5169 * The resource types have to be sorted otherwise
5170 * Windows Explorer can't display the version information.
5172 tree->children = g_slist_insert_sorted (tree->children,
5173 type_node, resource_tree_compare_by_id);
5176 /* Create res node if neccesary */
5178 for (l = type_node->children; l; l = l->next)
5179 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5180 res_node = (ResTreeNode*)l->data;
5185 res_node = g_new0 (ResTreeNode, 1);
5186 res_node->id = win32_res->res_id;
5187 type_node->children = g_slist_append (type_node->children, res_node);
5190 res_node->children = g_slist_append (res_node->children, lang_node);
5197 * resource_tree_encode:
5199 * Encode the resource tree into the format used in the PE file.
5202 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5205 MonoPEResourceDir dir;
5206 MonoPEResourceDirEntry dir_entry;
5207 MonoPEResourceDataEntry data_entry;
5209 guint32 res_id_entries;
5212 * For the format of the resource directory, see the article
5213 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5217 memset (&dir, 0, sizeof (dir));
5218 memset (&dir_entry, 0, sizeof (dir_entry));
5219 memset (&data_entry, 0, sizeof (data_entry));
5221 g_assert (sizeof (dir) == 16);
5222 g_assert (sizeof (dir_entry) == 8);
5223 g_assert (sizeof (data_entry) == 16);
5225 node->offset = p - begin;
5227 /* IMAGE_RESOURCE_DIRECTORY */
5228 res_id_entries = g_slist_length (node->children);
5229 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5231 memcpy (p, &dir, sizeof (dir));
5234 /* Reserve space for entries */
5236 p += sizeof (dir_entry) * res_id_entries;
5238 /* Write children */
5239 for (l = node->children; l; l = l->next) {
5240 ResTreeNode *child = (ResTreeNode*)l->data;
5242 if (child->win32_res) {
5245 child->offset = p - begin;
5247 /* IMAGE_RESOURCE_DATA_ENTRY */
5248 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5249 size = mono_array_length (child->win32_res->res_data);
5250 data_entry.rde_size = GUINT32_TO_LE (size);
5252 memcpy (p, &data_entry, sizeof (data_entry));
5253 p += sizeof (data_entry);
5255 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5258 resource_tree_encode (child, begin, p, &p);
5262 /* IMAGE_RESOURCE_ENTRY */
5263 for (l = node->children; l; l = l->next) {
5264 ResTreeNode *child = (ResTreeNode*)l->data;
5266 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5267 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5269 memcpy (entries, &dir_entry, sizeof (dir_entry));
5270 entries += sizeof (dir_entry);
5277 resource_tree_free (ResTreeNode * node)
5280 for (list = node->children; list; list = list->next)
5281 resource_tree_free ((ResTreeNode*)list->data);
5282 g_slist_free(node->children);
5287 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5292 MonoReflectionWin32Resource *win32_res;
5295 if (!assemblyb->win32_resources)
5299 * Resources are stored in a three level tree inside the PE file.
5300 * - level one contains a node for each type of resource
5301 * - level two contains a node for each resource
5302 * - level three contains a node for each instance of a resource for a
5303 * specific language.
5306 tree = resource_tree_create (assemblyb->win32_resources);
5308 /* Estimate the size of the encoded tree */
5310 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5311 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5312 size += mono_array_length (win32_res->res_data);
5314 /* Directory structure */
5315 size += mono_array_length (assemblyb->win32_resources) * 256;
5316 p = buf = g_malloc (size);
5318 resource_tree_encode (tree, p, p, &p);
5320 g_assert (p - buf <= size);
5322 assembly->win32_res = g_malloc (p - buf);
5323 assembly->win32_res_size = p - buf;
5324 memcpy (assembly->win32_res, buf, p - buf);
5327 resource_tree_free (tree);
5331 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5333 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5336 p += sizeof (MonoPEResourceDir);
5337 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5338 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5339 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5340 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5341 fixup_resource_directory (res_section, child, rva);
5343 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5344 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5347 p += sizeof (MonoPEResourceDirEntry);
5352 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5355 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5356 g_error ("WriteFile returned %d\n", GetLastError ());
5360 * mono_image_create_pefile:
5361 * @mb: a module builder object
5363 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5364 * assembly->pefile where it can be easily retrieved later in chunks.
5367 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5369 MonoMSDOSHeader *msdos;
5370 MonoDotNetHeader *header;
5371 MonoSectionTable *section;
5372 MonoCLIHeader *cli_header;
5373 guint32 size, image_size, virtual_base, text_offset;
5374 guint32 header_start, section_start, file_offset, virtual_offset;
5375 MonoDynamicImage *assembly;
5376 MonoReflectionAssemblyBuilder *assemblyb;
5377 MonoDynamicStream pefile_stream = {0};
5378 MonoDynamicStream *pefile = &pefile_stream;
5380 guint32 *rva, value;
5382 static const unsigned char msheader[] = {
5383 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5384 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5387 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5388 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5389 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5390 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5393 assemblyb = mb->assemblyb;
5395 mono_image_basic_init (assemblyb);
5396 assembly = mb->dynamic_image;
5398 assembly->pe_kind = assemblyb->pe_kind;
5399 assembly->machine = assemblyb->machine;
5400 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5401 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5403 mono_image_build_metadata (mb);
5405 if (mb->is_main && assemblyb->resources) {
5406 int len = mono_array_length (assemblyb->resources);
5407 for (i = 0; i < len; ++i)
5408 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5411 if (mb->resources) {
5412 int len = mono_array_length (mb->resources);
5413 for (i = 0; i < len; ++i)
5414 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5417 build_compressed_metadata (assembly);
5420 assembly_add_win32_resources (assembly, assemblyb);
5422 nsections = calc_section_size (assembly);
5424 /* The DOS header and stub */
5425 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5426 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5428 /* the dotnet header */
5429 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5431 /* the section tables */
5432 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5434 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5435 virtual_offset = VIRT_ALIGN;
5438 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5439 if (!assembly->sections [i].size)
5442 file_offset += FILE_ALIGN - 1;
5443 file_offset &= ~(FILE_ALIGN - 1);
5444 virtual_offset += VIRT_ALIGN - 1;
5445 virtual_offset &= ~(VIRT_ALIGN - 1);
5447 assembly->sections [i].offset = file_offset;
5448 assembly->sections [i].rva = virtual_offset;
5450 file_offset += assembly->sections [i].size;
5451 virtual_offset += assembly->sections [i].size;
5452 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5455 file_offset += FILE_ALIGN - 1;
5456 file_offset &= ~(FILE_ALIGN - 1);
5458 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5460 /* back-patch info */
5461 msdos = (MonoMSDOSHeader*)pefile->data;
5462 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5464 header = (MonoDotNetHeader*)(pefile->data + header_start);
5465 header->pesig [0] = 'P';
5466 header->pesig [1] = 'E';
5468 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5469 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5470 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5471 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5472 if (assemblyb->pekind == 1) {
5474 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5477 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5480 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5482 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5483 header->pe.pe_major = 6;
5484 header->pe.pe_minor = 0;
5485 size = assembly->sections [MONO_SECTION_TEXT].size;
5486 size += FILE_ALIGN - 1;
5487 size &= ~(FILE_ALIGN - 1);
5488 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5489 size = assembly->sections [MONO_SECTION_RSRC].size;
5490 size += FILE_ALIGN - 1;
5491 size &= ~(FILE_ALIGN - 1);
5492 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5493 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5494 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5495 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5496 /* pe_rva_entry_point always at the beginning of the text section */
5497 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5499 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5500 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5501 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5502 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5503 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5504 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5505 size = section_start;
5506 size += FILE_ALIGN - 1;
5507 size &= ~(FILE_ALIGN - 1);
5508 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5510 size += VIRT_ALIGN - 1;
5511 size &= ~(VIRT_ALIGN - 1);
5512 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5515 // Translate the PEFileKind value to the value expected by the Windows loader
5521 // PEFileKinds.Dll == 1
5522 // PEFileKinds.ConsoleApplication == 2
5523 // PEFileKinds.WindowApplication == 3
5526 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5527 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5529 if (assemblyb->pekind == 3)
5534 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5536 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5537 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5538 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5539 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5540 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5541 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5543 /* fill data directory entries */
5545 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5546 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5548 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5549 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5551 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5552 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5553 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5554 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5555 /* patch entrypoint name */
5556 if (assemblyb->pekind == 1)
5557 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5559 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5560 /* patch imported function RVA name */
5561 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5562 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5564 /* the import table */
5565 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5566 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5567 /* patch imported dll RVA name and other entries in the dir */
5568 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5569 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5570 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5571 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5572 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5573 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5575 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5576 value = (assembly->text_rva + assembly->imp_names_offset);
5577 *p++ = (value) & 0xff;
5578 *p++ = (value >> 8) & (0xff);
5579 *p++ = (value >> 16) & (0xff);
5580 *p++ = (value >> 24) & (0xff);
5582 /* the CLI header info */
5583 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5584 cli_header->ch_size = GUINT32_FROM_LE (72);
5585 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5586 if (mono_framework_version () > 1)
5587 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5589 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5590 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5591 if (assemblyb->entry_point) {
5592 guint32 table_idx = 0;
5593 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5594 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5595 table_idx = methodb->table_idx;
5597 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5599 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5601 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5603 /* The embedded managed resources */
5604 text_offset = assembly->text_rva + assembly->code.index;
5605 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5606 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5607 text_offset += assembly->resources.index;
5608 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5609 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5610 text_offset += assembly->meta_size;
5611 if (assembly->strong_name_size) {
5612 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5613 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5614 text_offset += assembly->strong_name_size;
5617 /* write the section tables and section content */
5618 section = (MonoSectionTable*)(pefile->data + section_start);
5619 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5620 static const char section_names [][7] = {
5621 ".text", ".rsrc", ".reloc"
5623 if (!assembly->sections [i].size)
5625 strcpy (section->st_name, section_names [i]);
5626 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5627 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5628 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5629 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5630 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5631 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5632 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5636 checked_write_file (file, pefile->data, pefile->index);
5638 mono_dynamic_stream_reset (pefile);
5640 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5641 if (!assembly->sections [i].size)
5644 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5645 g_error ("SetFilePointer returned %d\n", GetLastError ());
5648 case MONO_SECTION_TEXT:
5649 /* patch entry point */
5650 p = (guchar*)(assembly->code.data + 2);
5651 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5652 *p++ = (value) & 0xff;
5653 *p++ = (value >> 8) & 0xff;
5654 *p++ = (value >> 16) & 0xff;
5655 *p++ = (value >> 24) & 0xff;
5657 checked_write_file (file, assembly->code.data, assembly->code.index);
5658 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5659 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5660 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5663 g_free (assembly->image.raw_metadata);
5665 case MONO_SECTION_RELOC: {
5669 guint16 type_and_offset;
5673 g_assert (sizeof (reloc) == 12);
5675 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5676 reloc.block_size = GUINT32_FROM_LE (12);
5679 * the entrypoint is always at the start of the text section
5680 * 3 is IMAGE_REL_BASED_HIGHLOW
5681 * 2 is patch_size_rva - text_rva
5683 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5686 checked_write_file (file, &reloc, sizeof (reloc));
5690 case MONO_SECTION_RSRC:
5691 if (assembly->win32_res) {
5693 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5694 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5695 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5699 g_assert_not_reached ();
5703 /* check that the file is properly padded */
5704 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5705 g_error ("SetFilePointer returned %d\n", GetLastError ());
5706 if (! SetEndOfFile (file))
5707 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5709 mono_dynamic_stream_reset (&assembly->code);
5710 mono_dynamic_stream_reset (&assembly->us);
5711 mono_dynamic_stream_reset (&assembly->blob);
5712 mono_dynamic_stream_reset (&assembly->guid);
5713 mono_dynamic_stream_reset (&assembly->sheap);
5715 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5716 g_hash_table_destroy (assembly->blob_cache);
5717 assembly->blob_cache = NULL;
5720 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5723 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5725 g_assert_not_reached ();
5728 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5730 #ifndef DISABLE_REFLECTION_EMIT
5732 MonoReflectionModule *
5733 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5737 MonoImageOpenStatus status;
5738 MonoDynamicAssembly *assembly;
5739 guint32 module_count;
5740 MonoImage **new_modules;
5741 gboolean *new_modules_loaded;
5743 name = mono_string_to_utf8 (fileName);
5745 image = mono_image_open (name, &status);
5748 if (status == MONO_IMAGE_ERROR_ERRNO)
5749 exc = mono_get_exception_file_not_found (fileName);
5751 exc = mono_get_exception_bad_image_format (name);
5753 mono_raise_exception (exc);
5758 assembly = ab->dynamic_assembly;
5759 image->assembly = (MonoAssembly*)assembly;
5761 module_count = image->assembly->image->module_count;
5762 new_modules = g_new0 (MonoImage *, module_count + 1);
5763 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5765 if (image->assembly->image->modules)
5766 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5767 if (image->assembly->image->modules_loaded)
5768 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5769 new_modules [module_count] = image;
5770 new_modules_loaded [module_count] = TRUE;
5771 mono_image_addref (image);
5773 g_free (image->assembly->image->modules);
5774 image->assembly->image->modules = new_modules;
5775 image->assembly->image->modules_loaded = new_modules_loaded;
5776 image->assembly->image->module_count ++;
5778 mono_assembly_load_references (image, &status);
5780 mono_image_close (image);
5781 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5784 return mono_module_get_object (mono_domain_get (), image);
5787 #endif /* DISABLE_REFLECTION_EMIT */
5790 * We need to return always the same object for MethodInfo, FieldInfo etc..
5791 * but we need to consider the reflected type.
5792 * type uses a different hash, since it uses custom hash/equal functions.
5797 MonoClass *refclass;
5801 reflected_equal (gconstpointer a, gconstpointer b) {
5802 const ReflectedEntry *ea = a;
5803 const ReflectedEntry *eb = b;
5805 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5809 reflected_hash (gconstpointer a) {
5810 const ReflectedEntry *ea = a;
5811 return mono_aligned_addr_hash (ea->item);
5814 #define CHECK_OBJECT(t,p,k) \
5820 mono_domain_lock (domain); \
5821 if (!domain->refobject_hash) \
5822 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5823 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5824 mono_domain_unlock (domain); \
5827 mono_domain_unlock (domain); \
5830 #ifdef HAVE_BOEHM_GC
5831 /* ReflectedEntry doesn't need to be GC tracked */
5832 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5833 #define FREE_REFENTRY(entry) g_free ((entry))
5834 #define REFENTRY_REQUIRES_CLEANUP
5836 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5838 #define FREE_REFENTRY(entry)
5841 #define CACHE_OBJECT(t,p,o,k) \
5844 ReflectedEntry pe; \
5846 pe.refclass = (k); \
5847 mono_domain_lock (domain); \
5848 if (!domain->refobject_hash) \
5849 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5850 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5852 ReflectedEntry *e = ALLOC_REFENTRY; \
5854 e->refclass = (k); \
5855 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5858 mono_domain_unlock (domain); \
5863 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5865 mono_domain_lock (domain);
5866 if (domain->refobject_hash) {
5868 gpointer orig_pe, orig_value;
5871 pe.refclass = klass;
5872 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5873 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5874 FREE_REFENTRY (orig_pe);
5877 mono_domain_unlock (domain);
5880 #ifdef REFENTRY_REQUIRES_CLEANUP
5882 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5884 FREE_REFENTRY (key);
5889 mono_reflection_cleanup_domain (MonoDomain *domain)
5891 if (domain->refobject_hash) {
5892 /*let's avoid scanning the whole hashtable if not needed*/
5893 #ifdef REFENTRY_REQUIRES_CLEANUP
5894 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5896 mono_g_hash_table_destroy (domain->refobject_hash);
5897 domain->refobject_hash = NULL;
5901 #ifndef DISABLE_REFLECTION_EMIT
5903 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5905 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5909 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5911 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5915 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5917 MonoDynamicImage *image = moduleb->dynamic_image;
5918 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5921 MonoImage **new_modules;
5924 * FIXME: we already created an image in mono_image_basic_init (), but
5925 * we don't know which module it belongs to, since that is only
5926 * determined at assembly save time.
5928 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5929 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5931 moduleb->module.image = &image->image;
5932 moduleb->dynamic_image = image;
5933 register_module (mono_object_domain (moduleb), moduleb, image);
5935 /* register the module with the assembly */
5936 ass = ab->dynamic_assembly->assembly.image;
5937 module_count = ass->module_count;
5938 new_modules = g_new0 (MonoImage *, module_count + 1);
5941 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5942 new_modules [module_count] = &image->image;
5943 mono_image_addref (&image->image);
5945 g_free (ass->modules);
5946 ass->modules = new_modules;
5947 ass->module_count ++;
5952 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
5954 MonoDynamicImage *image = moduleb->dynamic_image;
5956 g_assert (type->type);
5957 image->wrappers_type = mono_class_from_mono_type (type->type);
5963 * mono_assembly_get_object:
5964 * @domain: an app domain
5965 * @assembly: an assembly
5967 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5969 MonoReflectionAssembly*
5970 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5972 static MonoClass *System_Reflection_Assembly;
5973 MonoReflectionAssembly *res;
5975 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5976 if (!System_Reflection_Assembly)
5977 System_Reflection_Assembly = mono_class_from_name (
5978 mono_defaults.corlib, "System.Reflection", "Assembly");
5979 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5980 res->assembly = assembly;
5982 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5987 MonoReflectionModule*
5988 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5990 static MonoClass *System_Reflection_Module;
5991 MonoReflectionModule *res;
5994 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5995 if (!System_Reflection_Module)
5996 System_Reflection_Module = mono_class_from_name (
5997 mono_defaults.corlib, "System.Reflection", "Module");
5998 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6001 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6003 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6004 basename = g_path_get_basename (image->name);
6005 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6006 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6010 if (image->assembly->image == image) {
6011 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6015 if (image->assembly->image->modules) {
6016 for (i = 0; i < image->assembly->image->module_count; i++) {
6017 if (image->assembly->image->modules [i] == image)
6018 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6020 g_assert (res->token);
6024 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6027 MonoReflectionModule*
6028 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6030 static MonoClass *System_Reflection_Module;
6031 MonoReflectionModule *res;
6032 MonoTableInfo *table;
6033 guint32 cols [MONO_FILE_SIZE];
6035 guint32 i, name_idx;
6038 if (!System_Reflection_Module)
6039 System_Reflection_Module = mono_class_from_name (
6040 mono_defaults.corlib, "System.Reflection", "Module");
6041 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6043 table = &image->tables [MONO_TABLE_FILE];
6044 g_assert (table_index < table->rows);
6045 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6048 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6049 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6051 /* Check whenever the row has a corresponding row in the moduleref table */
6052 table = &image->tables [MONO_TABLE_MODULEREF];
6053 for (i = 0; i < table->rows; ++i) {
6054 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6055 val = mono_metadata_string_heap (image, name_idx);
6056 if (strcmp (val, name) == 0)
6057 res->image = image->modules [i];
6060 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6061 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6062 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6063 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6064 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6070 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6072 if ((t1->type != t2->type) ||
6073 (t1->byref != t2->byref))
6077 case MONO_TYPE_VOID:
6078 case MONO_TYPE_BOOLEAN:
6079 case MONO_TYPE_CHAR:
6090 case MONO_TYPE_STRING:
6093 case MONO_TYPE_OBJECT:
6094 case MONO_TYPE_TYPEDBYREF:
6096 case MONO_TYPE_VALUETYPE:
6097 case MONO_TYPE_CLASS:
6098 case MONO_TYPE_SZARRAY:
6099 return t1->data.klass == t2->data.klass;
6101 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6102 case MONO_TYPE_ARRAY:
6103 if (t1->data.array->rank != t2->data.array->rank)
6105 return t1->data.array->eklass == t2->data.array->eklass;
6106 case MONO_TYPE_GENERICINST: {
6108 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6109 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6110 if (i1->type_argc != i2->type_argc)
6112 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6113 &t2->data.generic_class->container_class->byval_arg))
6115 /* FIXME: we should probably just compare the instance pointers directly. */
6116 for (i = 0; i < i1->type_argc; ++i) {
6117 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6123 case MONO_TYPE_MVAR:
6124 return t1->data.generic_param == t2->data.generic_param;
6126 g_error ("implement type compare for %0x!", t1->type);
6134 mymono_metadata_type_hash (MonoType *t1)
6140 hash |= t1->byref << 6; /* do not collide with t1->type values */
6142 case MONO_TYPE_VALUETYPE:
6143 case MONO_TYPE_CLASS:
6144 case MONO_TYPE_SZARRAY:
6145 /* check if the distribution is good enough */
6146 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6148 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6149 case MONO_TYPE_GENERICINST: {
6151 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6152 hash += g_str_hash (t1->data.generic_class->container_class->name);
6154 for (i = 0; i < inst->type_argc; ++i) {
6155 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6164 static MonoReflectionGenericClass*
6165 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6167 static MonoClass *System_Reflection_MonoGenericClass;
6168 MonoReflectionGenericClass *res;
6169 MonoClass *klass, *gklass;
6170 MonoGenericInst *ginst;
6171 MonoArray *type_args;
6174 if (!System_Reflection_MonoGenericClass) {
6175 System_Reflection_MonoGenericClass = mono_class_from_name (
6176 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6177 g_assert (System_Reflection_MonoGenericClass);
6180 klass = mono_class_from_mono_type (geninst);
6181 gklass = klass->generic_class->container_class;
6183 mono_class_init (klass);
6186 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6188 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6191 res->type.type = geninst;
6192 g_assert (gklass->reflection_info);
6193 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6194 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6196 ginst = klass->generic_class->context.class_inst;
6197 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6198 for (i = 0; i < ginst->type_argc; ++i)
6199 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6200 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6206 verify_safe_for_managed_space (MonoType *type)
6208 switch (type->type) {
6210 case MONO_TYPE_ARRAY:
6211 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6213 return verify_safe_for_managed_space (type->data.type);
6214 case MONO_TYPE_SZARRAY:
6215 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6216 case MONO_TYPE_GENERICINST: {
6217 MonoGenericInst *inst = type->data.generic_class->inst;
6221 for (i = 0; i < inst->type_argc; ++i)
6222 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6228 case MONO_TYPE_MVAR:
6235 * mono_type_get_object:
6236 * @domain: an app domain
6239 * Return an System.MonoType object representing the type @type.
6242 mono_type_get_object (MonoDomain *domain, MonoType *type)
6244 MonoReflectionType *res;
6245 MonoClass *klass = mono_class_from_mono_type (type);
6247 /*we must avoid using @type as it might have come
6248 * from a mono_metadata_type_dup and the caller
6249 * expects that is can be freed.
6250 * Using the right type from
6252 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6254 /* void is very common */
6255 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6256 return (MonoReflectionType*)domain->typeof_void;
6259 * If the vtable of the given class was already created, we can use
6260 * the MonoType from there and avoid all locking and hash table lookups.
6262 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6263 * that the resulting object is different.
6265 if (type == &klass->byval_arg && !klass->image->dynamic) {
6266 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6267 if (vtable && vtable->type)
6268 return vtable->type;
6271 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6272 mono_domain_lock (domain);
6273 if (!domain->type_hash)
6274 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6275 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6276 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6277 mono_domain_unlock (domain);
6278 mono_loader_unlock ();
6281 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6282 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6283 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6284 mono_g_hash_table_insert (domain->type_hash, type, res);
6285 mono_domain_unlock (domain);
6286 mono_loader_unlock ();
6290 if (!verify_safe_for_managed_space (type)) {
6291 mono_domain_unlock (domain);
6292 mono_loader_unlock ();
6293 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6296 if (klass->reflection_info && !klass->wastypebuilder) {
6297 /* g_assert_not_reached (); */
6298 /* should this be considered an error condition? */
6300 mono_domain_unlock (domain);
6301 mono_loader_unlock ();
6302 return klass->reflection_info;
6305 // FIXME: Get rid of this, do it in the icalls for Type
6306 mono_class_init (klass);
6308 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6310 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6313 mono_g_hash_table_insert (domain->type_hash, type, res);
6315 if (type->type == MONO_TYPE_VOID)
6316 domain->typeof_void = (MonoObject*)res;
6318 mono_domain_unlock (domain);
6319 mono_loader_unlock ();
6324 * mono_method_get_object:
6325 * @domain: an app domain
6327 * @refclass: the reflected type (can be NULL)
6329 * Return an System.Reflection.MonoMethod object representing the method @method.
6331 MonoReflectionMethod*
6332 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6335 * We use the same C representation for methods and constructors, but the type
6336 * name in C# is different.
6338 static MonoClass *System_Reflection_MonoMethod = NULL;
6339 static MonoClass *System_Reflection_MonoCMethod = NULL;
6340 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6341 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6343 MonoReflectionMethod *ret;
6345 if (method->is_inflated) {
6346 MonoReflectionGenericMethod *gret;
6348 refclass = method->klass;
6349 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6350 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6351 if (!System_Reflection_MonoGenericCMethod)
6352 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6353 klass = System_Reflection_MonoGenericCMethod;
6355 if (!System_Reflection_MonoGenericMethod)
6356 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6357 klass = System_Reflection_MonoGenericMethod;
6359 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6360 gret->method.method = method;
6361 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6362 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6363 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6367 refclass = method->klass;
6369 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6370 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6371 if (!System_Reflection_MonoCMethod)
6372 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6373 klass = System_Reflection_MonoCMethod;
6376 if (!System_Reflection_MonoMethod)
6377 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6378 klass = System_Reflection_MonoMethod;
6380 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6381 ret->method = method;
6382 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6383 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6387 * mono_method_clear_object:
6389 * Clear the cached reflection objects for the dynamic method METHOD.
6392 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6395 g_assert (method->dynamic);
6397 klass = method->klass;
6399 clear_cached_object (domain, method, klass);
6400 klass = klass->parent;
6402 /* Added by mono_param_get_objects () */
6403 clear_cached_object (domain, &(method->signature), NULL);
6404 klass = method->klass;
6406 clear_cached_object (domain, &(method->signature), klass);
6407 klass = klass->parent;
6412 * mono_field_get_object:
6413 * @domain: an app domain
6417 * Return an System.Reflection.MonoField object representing the field @field
6420 MonoReflectionField*
6421 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6423 MonoReflectionField *res;
6424 static MonoClass *monofield_klass;
6426 CHECK_OBJECT (MonoReflectionField *, field, klass);
6427 if (!monofield_klass)
6428 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6429 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6432 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6433 if (is_field_on_inst (field))
6434 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6436 res->attrs = field->type->attrs;
6437 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6438 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6442 * mono_property_get_object:
6443 * @domain: an app domain
6445 * @property: a property
6447 * Return an System.Reflection.MonoProperty object representing the property @property
6450 MonoReflectionProperty*
6451 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6453 MonoReflectionProperty *res;
6454 static MonoClass *monoproperty_klass;
6456 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6457 if (!monoproperty_klass)
6458 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6459 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6461 res->property = property;
6462 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6466 * mono_event_get_object:
6467 * @domain: an app domain
6471 * Return an System.Reflection.MonoEvent object representing the event @event
6474 MonoReflectionEvent*
6475 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6477 MonoReflectionEvent *res;
6478 MonoReflectionMonoEvent *mono_event;
6479 static MonoClass *monoevent_klass;
6481 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6482 if (!monoevent_klass)
6483 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6484 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6485 mono_event->klass = klass;
6486 mono_event->event = event;
6487 res = (MonoReflectionEvent*)mono_event;
6488 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6492 * mono_get_reflection_missing_object:
6493 * @domain: Domain where the object lives
6495 * Returns the System.Reflection.Missing.Value singleton object
6496 * (of type System.Reflection.Missing).
6498 * Used as the value for ParameterInfo.DefaultValue when Optional
6502 mono_get_reflection_missing_object (MonoDomain *domain)
6505 static MonoClassField *missing_value_field = NULL;
6507 if (!missing_value_field) {
6508 MonoClass *missing_klass;
6509 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6510 mono_class_init (missing_klass);
6511 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6512 g_assert (missing_value_field);
6514 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6520 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6523 *dbnull = mono_get_dbnull_object (domain);
6528 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6530 if (!*reflection_missing)
6531 *reflection_missing = mono_get_reflection_missing_object (domain);
6532 return *reflection_missing;
6536 * mono_param_get_objects:
6537 * @domain: an app domain
6540 * Return an System.Reflection.ParameterInfo array object representing the parameters
6541 * in the method @method.
6544 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6546 static MonoClass *System_Reflection_ParameterInfo;
6547 static MonoClass *System_Reflection_ParameterInfo_array;
6548 MonoArray *res = NULL;
6549 MonoReflectionMethod *member = NULL;
6550 MonoReflectionParameter *param = NULL;
6551 char **names, **blobs = NULL;
6552 guint32 *types = NULL;
6553 MonoType *type = NULL;
6554 MonoObject *dbnull = NULL;
6555 MonoObject *missing = NULL;
6556 MonoMarshalSpec **mspecs;
6557 MonoMethodSignature *sig;
6558 MonoVTable *pinfo_vtable;
6561 if (!System_Reflection_ParameterInfo_array) {
6564 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6565 mono_memory_barrier ();
6566 System_Reflection_ParameterInfo = klass;
6568 klass = mono_array_class_get (klass, 1);
6569 mono_memory_barrier ();
6570 System_Reflection_ParameterInfo_array = klass;
6573 if (!mono_method_signature (method)->param_count)
6574 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6576 /* Note: the cache is based on the address of the signature into the method
6577 * since we already cache MethodInfos with the method as keys.
6579 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6581 sig = mono_method_signature (method);
6582 member = mono_method_get_object (domain, method, refclass);
6583 names = g_new (char *, sig->param_count);
6584 mono_method_get_param_names (method, (const char **) names);
6586 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6587 mono_method_get_marshal_info (method, mspecs);
6589 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6590 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6591 for (i = 0; i < sig->param_count; ++i) {
6592 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6593 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6594 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6595 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6596 param->PositionImpl = i;
6597 param->AttrsImpl = sig->params [i]->attrs;
6599 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6600 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6601 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6603 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6607 blobs = g_new0 (char *, sig->param_count);
6608 types = g_new0 (guint32, sig->param_count);
6609 get_default_param_value_blobs (method, blobs, types);
6612 /* Build MonoType for the type from the Constant Table */
6614 type = g_new0 (MonoType, 1);
6615 type->type = types [i];
6616 type->data.klass = NULL;
6617 if (types [i] == MONO_TYPE_CLASS)
6618 type->data.klass = mono_defaults.object_class;
6619 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6620 /* For enums, types [i] contains the base type */
6622 type->type = MONO_TYPE_VALUETYPE;
6623 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6625 type->data.klass = mono_class_from_mono_type (type);
6627 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6629 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6630 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6631 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6632 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6634 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6640 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6642 mono_array_setref (res, i, param);
6649 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6651 mono_metadata_free_marshal_spec (mspecs [i]);
6654 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6658 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6660 return mono_param_get_objects_internal (domain, method, NULL);
6664 * mono_method_body_get_object:
6665 * @domain: an app domain
6668 * Return an System.Reflection.MethodBody object representing the method @method.
6670 MonoReflectionMethodBody*
6671 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6673 static MonoClass *System_Reflection_MethodBody = NULL;
6674 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6675 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6676 MonoReflectionMethodBody *ret;
6677 MonoMethodNormal *mn;
6678 MonoMethodHeader *header;
6679 guint32 method_rva, local_var_sig_token;
6681 unsigned char format, flags;
6684 if (!System_Reflection_MethodBody)
6685 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6686 if (!System_Reflection_LocalVariableInfo)
6687 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6688 if (!System_Reflection_ExceptionHandlingClause)
6689 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6691 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6693 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6694 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6695 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6696 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6698 mn = (MonoMethodNormal *)method;
6699 header = mono_method_get_header (method);
6701 /* Obtain local vars signature token */
6702 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6703 ptr = mono_image_rva_map (method->klass->image, method_rva);
6704 flags = *(const unsigned char *) ptr;
6705 format = flags & METHOD_HEADER_FORMAT_MASK;
6707 case METHOD_HEADER_TINY_FORMAT:
6708 local_var_sig_token = 0;
6710 case METHOD_HEADER_FAT_FORMAT:
6714 local_var_sig_token = read32 (ptr);
6717 g_assert_not_reached ();
6720 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6722 ret->init_locals = header->init_locals;
6723 ret->max_stack = header->max_stack;
6724 ret->local_var_sig_token = local_var_sig_token;
6725 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6726 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6729 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6730 for (i = 0; i < header->num_locals; ++i) {
6731 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6732 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6733 info->is_pinned = header->locals [i]->pinned;
6734 info->local_index = i;
6735 mono_array_setref (ret->locals, i, info);
6739 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6740 for (i = 0; i < header->num_clauses; ++i) {
6741 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6742 MonoExceptionClause *clause = &header->clauses [i];
6744 info->flags = clause->flags;
6745 info->try_offset = clause->try_offset;
6746 info->try_length = clause->try_len;
6747 info->handler_offset = clause->handler_offset;
6748 info->handler_length = clause->handler_len;
6749 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6750 info->filter_offset = clause->data.filter_offset;
6751 else if (clause->data.catch_class)
6752 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6754 mono_array_setref (ret->clauses, i, info);
6757 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6762 * mono_get_dbnull_object:
6763 * @domain: Domain where the object lives
6765 * Returns the System.DBNull.Value singleton object
6767 * Used as the value for ParameterInfo.DefaultValue
6770 mono_get_dbnull_object (MonoDomain *domain)
6773 static MonoClassField *dbnull_value_field = NULL;
6775 if (!dbnull_value_field) {
6776 MonoClass *dbnull_klass;
6777 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6778 mono_class_init (dbnull_klass);
6779 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6780 g_assert (dbnull_value_field);
6782 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6788 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6790 guint32 param_index, i, lastp, crow = 0;
6791 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6794 MonoClass *klass = method->klass;
6795 MonoImage *image = klass->image;
6796 MonoMethodSignature *methodsig = mono_method_signature (method);
6798 MonoTableInfo *constt;
6799 MonoTableInfo *methodt;
6800 MonoTableInfo *paramt;
6802 if (!methodsig->param_count)
6805 mono_class_init (klass);
6807 if (klass->image->dynamic) {
6808 MonoReflectionMethodAux *aux;
6809 if (method->is_inflated)
6810 method = ((MonoMethodInflated*)method)->declaring;
6811 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6812 if (aux && aux->param_defaults) {
6813 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6814 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6819 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6820 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6821 constt = &image->tables [MONO_TABLE_CONSTANT];
6823 idx = mono_method_get_index (method) - 1;
6824 g_assert (idx != -1);
6826 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6827 if (idx + 1 < methodt->rows)
6828 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6830 lastp = paramt->rows + 1;
6832 for (i = param_index; i < lastp; ++i) {
6835 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6836 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6838 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6841 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6846 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6847 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6848 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6855 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6860 MonoType *basetype = type;
6865 klass = mono_class_from_mono_type (type);
6866 if (klass->valuetype) {
6867 object = mono_object_new (domain, klass);
6868 retval = ((gchar *) object + sizeof (MonoObject));
6869 if (klass->enumtype)
6870 basetype = mono_class_enum_basetype (klass);
6875 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6882 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6886 memset (assembly, 0, sizeof (MonoAssemblyName));
6888 assembly->culture = "";
6889 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6891 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6894 while (g_ascii_isspace (*p) || *p == ',') {
6903 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6905 assembly->major = strtoul (p, &s, 10);
6906 if (s == p || *s != '.')
6909 assembly->minor = strtoul (p, &s, 10);
6910 if (s == p || *s != '.')
6913 assembly->build = strtoul (p, &s, 10);
6914 if (s == p || *s != '.')
6917 assembly->revision = strtoul (p, &s, 10);
6921 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6923 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6924 assembly->culture = "";
6927 assembly->culture = p;
6928 while (*p && *p != ',') {
6932 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6934 if (strncmp (p, "null", 4) == 0) {
6939 while (*p && *p != ',') {
6942 len = (p - start + 1);
6943 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6944 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6945 g_strlcpy ((char*)assembly->public_key_token, start, len);
6948 while (*p && *p != ',')
6952 while (g_ascii_isspace (*p) || *p == ',') {
6966 * mono_reflection_parse_type:
6969 * Parse a type name as accepted by the GetType () method and output the info
6970 * extracted in the info structure.
6971 * the name param will be mangled, so, make a copy before passing it to this function.
6972 * The fields in info will be valid until the memory pointed to by name is valid.
6974 * See also mono_type_get_name () below.
6976 * Returns: 0 on parse error.
6979 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6980 MonoTypeNameParse *info)
6982 char *start, *p, *w, *temp, *last_point, *startn;
6983 int in_modifiers = 0;
6984 int isbyref = 0, rank, arity = 0, i;
6986 start = p = w = name;
6988 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6989 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6990 info->name = info->name_space = NULL;
6991 info->nested = NULL;
6992 info->modifiers = NULL;
6993 info->type_arguments = NULL;
6995 /* last_point separates the namespace from the name */
6998 while (*p == ' ') p++, start++, w++, name++;
7003 *p = 0; /* NULL terminate the name */
7005 info->nested = g_list_append (info->nested, startn);
7006 /* we have parsed the nesting namespace + name */
7010 info->name_space = start;
7012 info->name = last_point + 1;
7014 info->name_space = (char *)"";
7033 i = strtol (p, &temp, 10);
7050 info->name_space = start;
7052 info->name = last_point + 1;
7054 info->name_space = (char *)"";
7061 if (isbyref) /* only one level allowed by the spec */
7064 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7068 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7074 info->type_arguments = g_ptr_array_new ();
7075 for (i = 0; i < arity; i++) {
7076 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7077 gboolean fqname = FALSE;
7079 g_ptr_array_add (info->type_arguments, subinfo);
7086 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7097 while (*p && (*p != ']'))
7105 if (g_ascii_isspace (*aname)) {
7112 !assembly_name_to_aname (&subinfo->assembly, aname))
7116 if (i + 1 < arity) {
7136 else if (*p == '*') /* '*' means unknown lower bound */
7137 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7144 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7155 if (g_ascii_isspace (*p)) {
7162 return 0; /* missing assembly name */
7163 if (!assembly_name_to_aname (&info->assembly, p))
7169 if (info->assembly.name)
7172 // *w = 0; /* terminate class name */
7174 if (!info->name || !*info->name)
7178 /* add other consistency checks */
7183 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7185 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7189 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7191 gboolean type_resolve = FALSE;
7193 MonoImage *rootimage = image;
7195 if (info->assembly.name) {
7196 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7197 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7199 * This could happen in the AOT compiler case when the search hook is not
7202 assembly = image->assembly;
7204 /* then we must load the assembly ourselve - see #60439 */
7205 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7209 image = assembly->image;
7210 } else if (!image) {
7211 image = mono_defaults.corlib;
7214 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7215 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7216 image = mono_defaults.corlib;
7217 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7224 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7229 gboolean bounded = FALSE;
7232 image = mono_defaults.corlib;
7235 klass = mono_class_from_name_case (image, info->name_space, info->name);
7237 klass = mono_class_from_name (image, info->name_space, info->name);
7240 for (mod = info->nested; mod; mod = mod->next) {
7241 gpointer iter = NULL;
7245 mono_class_init (parent);
7247 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7249 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7252 if (strcmp (klass->name, mod->data) == 0)
7261 mono_class_init (klass);
7263 if (info->type_arguments) {
7264 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7265 MonoReflectionType *the_type;
7269 for (i = 0; i < info->type_arguments->len; i++) {
7270 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7272 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7273 if (!type_args [i]) {
7279 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7281 instance = mono_reflection_bind_generic_parameters (
7282 the_type, info->type_arguments->len, type_args);
7288 klass = mono_class_from_mono_type (instance);
7291 for (mod = info->modifiers; mod; mod = mod->next) {
7292 modval = GPOINTER_TO_UINT (mod->data);
7293 if (!modval) { /* byref: must be last modifier */
7294 return &klass->this_arg;
7295 } else if (modval == -1) {
7296 klass = mono_ptr_class_get (&klass->byval_arg);
7297 } else if (modval == -2) {
7299 } else { /* array rank */
7300 klass = mono_bounded_array_class_get (klass, modval, bounded);
7302 mono_class_init (klass);
7305 return &klass->byval_arg;
7309 * mono_reflection_get_type:
7310 * @image: a metadata context
7311 * @info: type description structure
7312 * @ignorecase: flag for case-insensitive string compares
7313 * @type_resolve: whenever type resolve was already tried
7315 * Build a MonoType from the type description in @info.
7320 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7321 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7325 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7327 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7331 g_assert (assembly->dynamic);
7333 /* Enumerate all modules */
7336 if (abuilder->modules) {
7337 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7338 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7339 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7345 if (!type && abuilder->loaded_modules) {
7346 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7347 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7348 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7358 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7361 MonoReflectionAssembly *assembly;
7365 if (image && image->dynamic)
7366 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7368 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7371 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7378 *type_resolve = TRUE;
7381 /* Reconstruct the type name */
7382 fullName = g_string_new ("");
7383 if (info->name_space && (info->name_space [0] != '\0'))
7384 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7386 g_string_printf (fullName, "%s", info->name);
7387 for (mod = info->nested; mod; mod = mod->next)
7388 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7390 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7392 if (assembly->assembly->dynamic)
7393 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7395 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7398 g_string_free (fullName, TRUE);
7403 mono_reflection_free_type_info (MonoTypeNameParse *info)
7405 g_list_free (info->modifiers);
7406 g_list_free (info->nested);
7408 if (info->type_arguments) {
7411 for (i = 0; i < info->type_arguments->len; i++) {
7412 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7414 mono_reflection_free_type_info (subinfo);
7415 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7419 g_ptr_array_free (info->type_arguments, TRUE);
7424 * mono_reflection_type_from_name:
7426 * @image: a metadata context (can be NULL).
7428 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7429 * it defaults to get the type from @image or, if @image is NULL or loading
7430 * from it fails, uses corlib.
7434 mono_reflection_type_from_name (char *name, MonoImage *image)
7436 MonoType *type = NULL;
7437 MonoTypeNameParse info;
7440 /* Make a copy since parse_type modifies its argument */
7441 tmp = g_strdup (name);
7443 /*g_print ("requested type %s\n", str);*/
7444 if (mono_reflection_parse_type (tmp, &info)) {
7445 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7449 mono_reflection_free_type_info (&info);
7454 * mono_reflection_get_token:
7456 * Return the metadata token of OBJ which should be an object
7457 * representing a metadata element.
7460 mono_reflection_get_token (MonoObject *obj)
7465 klass = obj->vtable->klass;
7467 if (strcmp (klass->name, "MethodBuilder") == 0) {
7468 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7470 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7471 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7472 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7474 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7475 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7476 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7478 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7479 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7480 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7481 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7482 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7483 } else if (strcmp (klass->name, "MonoType") == 0) {
7484 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7485 token = mono_class_from_mono_type (type)->type_token;
7486 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7487 strcmp (klass->name, "MonoMethod") == 0 ||
7488 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7489 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7490 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7491 if (m->method->is_inflated) {
7492 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7493 return inflated->declaring->token;
7495 token = m->method->token;
7497 } else if (strcmp (klass->name, "MonoField") == 0) {
7498 MonoReflectionField *f = (MonoReflectionField*)obj;
7500 if (is_field_on_inst (f->field)) {
7501 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7502 int field_index = f->field - dgclass->fields;
7505 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7506 obj = dgclass->field_objects [field_index];
7507 return mono_reflection_get_token (obj);
7509 token = mono_class_get_field_token (f->field);
7510 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7511 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7513 token = mono_class_get_property_token (p->property);
7514 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7515 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7517 token = mono_class_get_event_token (p->event);
7518 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7519 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7521 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7522 } else if (strcmp (klass->name, "Module") == 0) {
7523 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7526 } else if (strcmp (klass->name, "Assembly") == 0) {
7527 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7529 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7530 MonoException *ex = mono_get_exception_not_implemented (msg);
7532 mono_raise_exception (ex);
7539 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7541 int slen, type = t->type;
7542 MonoClass *tklass = t->data.klass;
7548 case MONO_TYPE_BOOLEAN: {
7549 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7554 case MONO_TYPE_CHAR:
7556 case MONO_TYPE_I2: {
7557 guint16 *val = g_malloc (sizeof (guint16));
7562 #if SIZEOF_VOID_P == 4
7568 case MONO_TYPE_I4: {
7569 guint32 *val = g_malloc (sizeof (guint32));
7574 #if SIZEOF_VOID_P == 8
7575 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7579 case MONO_TYPE_I8: {
7580 guint64 *val = g_malloc (sizeof (guint64));
7585 case MONO_TYPE_R8: {
7586 double *val = g_malloc (sizeof (double));
7591 case MONO_TYPE_VALUETYPE:
7592 if (t->data.klass->enumtype) {
7593 type = mono_class_enum_basetype (t->data.klass)->type;
7596 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7599 case MONO_TYPE_STRING:
7600 if (*p == (char)0xFF) {
7604 slen = mono_metadata_decode_value (p, &p);
7606 return mono_string_new_len (mono_domain_get (), p, slen);
7607 case MONO_TYPE_CLASS: {
7610 if (*p == (char)0xFF) {
7615 slen = mono_metadata_decode_value (p, &p);
7616 n = g_memdup (p, slen + 1);
7618 t = mono_reflection_type_from_name (n, image);
7620 g_warning ("Cannot load type '%s'", n);
7624 return mono_type_get_object (mono_domain_get (), t);
7628 case MONO_TYPE_OBJECT: {
7631 MonoClass *subc = NULL;
7636 } else if (subt == 0x0E) {
7637 type = MONO_TYPE_STRING;
7639 } else if (subt == 0x1D) {
7640 MonoType simple_type = {{0}};
7645 /* See Partition II, Appendix B3 */
7646 etype = MONO_TYPE_OBJECT;
7647 type = MONO_TYPE_SZARRAY;
7648 simple_type.type = etype;
7649 tklass = mono_class_from_mono_type (&simple_type);
7651 } else if (subt == 0x55) {
7654 slen = mono_metadata_decode_value (p, &p);
7655 n = g_memdup (p, slen + 1);
7657 t = mono_reflection_type_from_name (n, image);
7659 g_error ("Cannot load type '%s'", n);
7662 subc = mono_class_from_mono_type (t);
7663 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7664 MonoType simple_type = {{0}};
7665 simple_type.type = subt;
7666 subc = mono_class_from_mono_type (&simple_type);
7668 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7670 val = load_cattr_value (image, &subc->byval_arg, p, end);
7671 obj = mono_object_new (mono_domain_get (), subc);
7672 g_assert (!subc->has_references);
7673 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7677 case MONO_TYPE_SZARRAY: {
7679 guint32 i, alen, basetype;
7682 if (alen == 0xffffffff) {
7686 arr = mono_array_new (mono_domain_get(), tklass, alen);
7687 basetype = tklass->byval_arg.type;
7688 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7689 basetype = mono_class_enum_basetype (tklass)->type;
7694 case MONO_TYPE_BOOLEAN:
7695 for (i = 0; i < alen; i++) {
7696 MonoBoolean val = *p++;
7697 mono_array_set (arr, MonoBoolean, i, val);
7700 case MONO_TYPE_CHAR:
7703 for (i = 0; i < alen; i++) {
7704 guint16 val = read16 (p);
7705 mono_array_set (arr, guint16, i, val);
7712 for (i = 0; i < alen; i++) {
7713 guint32 val = read32 (p);
7714 mono_array_set (arr, guint32, i, val);
7719 for (i = 0; i < alen; i++) {
7722 mono_array_set (arr, double, i, val);
7728 for (i = 0; i < alen; i++) {
7729 guint64 val = read64 (p);
7730 mono_array_set (arr, guint64, i, val);
7734 case MONO_TYPE_CLASS:
7735 case MONO_TYPE_OBJECT:
7736 case MONO_TYPE_STRING:
7737 for (i = 0; i < alen; i++) {
7738 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7739 mono_array_setref (arr, i, item);
7743 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7749 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7755 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7757 static MonoClass *klass;
7758 static MonoMethod *ctor;
7760 void *params [2], *unboxed;
7763 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7765 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7767 params [0] = mono_type_get_object (mono_domain_get (), t);
7769 retval = mono_object_new (mono_domain_get (), klass);
7770 unboxed = mono_object_unbox (retval);
7771 mono_runtime_invoke (ctor, unboxed, params, NULL);
7777 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7779 static MonoClass *klass;
7780 static MonoMethod *ctor;
7782 void *unboxed, *params [2];
7785 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7787 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7790 params [1] = typedarg;
7791 retval = mono_object_new (mono_domain_get (), klass);
7792 unboxed = mono_object_unbox (retval);
7793 mono_runtime_invoke (ctor, unboxed, params, NULL);
7799 type_is_reference (MonoType *type)
7801 switch (type->type) {
7802 case MONO_TYPE_BOOLEAN:
7803 case MONO_TYPE_CHAR:
7816 case MONO_TYPE_VALUETYPE:
7824 free_param_data (MonoMethodSignature *sig, void **params) {
7826 for (i = 0; i < sig->param_count; ++i) {
7827 if (!type_is_reference (sig->params [i]))
7828 g_free (params [i]);
7833 * Find the field index in the metadata FieldDef table.
7836 find_field_index (MonoClass *klass, MonoClassField *field) {
7839 for (i = 0; i < klass->field.count; ++i) {
7840 if (field == &klass->fields [i])
7841 return klass->field.first + 1 + i;
7847 * Find the property index in the metadata Property table.
7850 find_property_index (MonoClass *klass, MonoProperty *property) {
7853 for (i = 0; i < klass->ext->property.count; ++i) {
7854 if (property == &klass->ext->properties [i])
7855 return klass->ext->property.first + 1 + i;
7861 * Find the event index in the metadata Event table.
7864 find_event_index (MonoClass *klass, MonoEvent *event) {
7867 for (i = 0; i < klass->ext->event.count; ++i) {
7868 if (event == &klass->ext->events [i])
7869 return klass->ext->event.first + 1 + i;
7875 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7877 const char *p = (const char*)data;
7879 guint32 i, j, num_named;
7881 void *params_buf [32];
7883 MonoMethodSignature *sig;
7885 mono_class_init (method->klass);
7888 attr = mono_object_new (mono_domain_get (), method->klass);
7889 mono_runtime_invoke (method, attr, NULL, NULL);
7893 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7896 /*g_print ("got attr %s\n", method->klass->name);*/
7898 sig = mono_method_signature (method);
7899 if (sig->param_count < 32)
7900 params = params_buf;
7902 /* Allocate using GC so it gets GC tracking */
7903 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7907 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7908 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7912 attr = mono_object_new (mono_domain_get (), method->klass);
7913 mono_runtime_invoke (method, attr, params, NULL);
7914 free_param_data (method->signature, params);
7915 num_named = read16 (named);
7917 for (j = 0; j < num_named; j++) {
7919 char *name, named_type, data_type;
7920 named_type = *named++;
7921 data_type = *named++; /* type of data */
7922 if (data_type == MONO_TYPE_SZARRAY)
7923 data_type = *named++;
7924 if (data_type == MONO_TYPE_ENUM) {
7927 type_len = mono_metadata_decode_blob_size (named, &named);
7928 type_name = g_malloc (type_len + 1);
7929 memcpy (type_name, named, type_len);
7930 type_name [type_len] = 0;
7932 /* FIXME: lookup the type and check type consistency */
7935 name_len = mono_metadata_decode_blob_size (named, &named);
7936 name = g_malloc (name_len + 1);
7937 memcpy (name, named, name_len);
7938 name [name_len] = 0;
7940 if (named_type == 0x53) {
7941 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7942 void *val = load_cattr_value (image, field->type, named, &named);
7943 mono_field_set_value (attr, field, val);
7944 if (!type_is_reference (field->type))
7946 } else if (named_type == 0x54) {
7949 MonoType *prop_type;
7951 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7952 /* can we have more that 1 arg in a custom attr named property? */
7953 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7954 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7955 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7956 mono_property_set_value (prop, attr, pparams, NULL);
7957 if (!type_is_reference (prop_type))
7958 g_free (pparams [0]);
7963 if (params != params_buf)
7964 mono_gc_free_fixed (params);
7970 * mono_reflection_create_custom_attr_data_args:
7972 * Create an array of typed and named arguments from the cattr blob given by DATA.
7973 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
7974 * NAMED_ARG_INFO will contain information about the named arguments.
7977 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
7979 MonoArray *typedargs, *namedargs;
7980 MonoClass *attrklass;
7982 const char *p = (const char*)data;
7984 guint32 i, j, num_named;
7985 CattrNamedArg *arginfo = NULL;
7987 mono_class_init (method->klass);
7991 *named_arg_info = NULL;
7993 domain = mono_domain_get ();
7995 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7998 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8002 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8006 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8007 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8008 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8009 mono_array_setref (typedargs, i, obj);
8011 if (!type_is_reference (mono_method_signature (method)->params [i]))
8016 num_named = read16 (named);
8017 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8019 attrklass = method->klass;
8021 arginfo = g_new0 (CattrNamedArg, num_named);
8022 *named_arg_info = arginfo;
8024 for (j = 0; j < num_named; j++) {
8026 char *name, named_type, data_type;
8027 named_type = *named++;
8028 data_type = *named++; /* type of data */
8029 if (data_type == MONO_TYPE_SZARRAY)
8030 data_type = *named++;
8031 if (data_type == MONO_TYPE_ENUM) {
8034 type_len = mono_metadata_decode_blob_size (named, &named);
8035 type_name = g_malloc (type_len + 1);
8036 memcpy (type_name, named, type_len);
8037 type_name [type_len] = 0;
8039 /* FIXME: lookup the type and check type consistency */
8042 name_len = mono_metadata_decode_blob_size (named, &named);
8043 name = g_malloc (name_len + 1);
8044 memcpy (name, named, name_len);
8045 name [name_len] = 0;
8047 if (named_type == 0x53) {
8049 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8052 arginfo [j].type = field->type;
8053 arginfo [j].field = field;
8055 val = load_cattr_value (image, field->type, named, &named);
8056 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8057 mono_array_setref (namedargs, j, obj);
8058 if (!type_is_reference (field->type))
8060 } else if (named_type == 0x54) {
8062 MonoType *prop_type;
8063 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8066 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8067 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8069 arginfo [j].type = prop_type;
8070 arginfo [j].prop = prop;
8072 val = load_cattr_value (image, prop_type, named, &named);
8073 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8074 mono_array_setref (namedargs, j, obj);
8075 if (!type_is_reference (prop_type))
8081 *typed_args = typedargs;
8082 *named_args = namedargs;
8086 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8088 MonoArray *typedargs, *namedargs;
8089 static MonoMethod *ctor;
8093 CattrNamedArg *arginfo;
8096 mono_class_init (method->klass);
8099 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8101 domain = mono_domain_get ();
8103 /* This is for Attributes with no parameters */
8104 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8105 params [0] = mono_method_get_object (domain, method, NULL);
8106 params [1] = params [2] = NULL;
8107 mono_runtime_invoke (method, attr, params, NULL);
8111 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8112 if (!typedargs || !namedargs)
8115 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8116 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8117 MonoObject *typedarg;
8119 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8120 mono_array_setref (typedargs, i, typedarg);
8123 for (i = 0; i < mono_array_length (namedargs); ++i) {
8124 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8125 MonoObject *typedarg, *namedarg, *minfo;
8127 if (arginfo [i].prop)
8128 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8130 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8132 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8133 namedarg = create_cattr_named_arg (minfo, typedarg);
8135 mono_array_setref (namedargs, i, namedarg);
8138 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8139 params [0] = mono_method_get_object (domain, method, NULL);
8140 params [1] = typedargs;
8141 params [2] = namedargs;
8142 mono_runtime_invoke (ctor, attr, params, NULL);
8147 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8153 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8154 for (i = 0; i < cinfo->num_attrs; ++i) {
8155 if (!cinfo->attrs [i].ctor)
8156 /* The cattr type is not finished yet */
8157 /* We should include the type name but cinfo doesn't contain it */
8158 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8159 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8160 mono_array_setref (result, i, attr);
8166 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8173 for (i = 0; i < cinfo->num_attrs; ++i) {
8174 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8178 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8180 for (i = 0; i < cinfo->num_attrs; ++i) {
8181 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8182 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8183 mono_array_setref (result, n, attr);
8191 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8197 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8198 for (i = 0; i < cinfo->num_attrs; ++i) {
8199 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8200 mono_array_setref (result, i, attr);
8206 * mono_custom_attrs_from_index:
8208 * Returns: NULL if no attributes are found or if a loading error occurs.
8211 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8213 guint32 mtoken, i, len;
8214 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8216 MonoCustomAttrInfo *ainfo;
8217 GList *tmp, *list = NULL;
8220 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8222 i = mono_metadata_custom_attrs_from_index (image, idx);
8226 while (i < ca->rows) {
8227 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8229 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8232 len = g_list_length (list);
8235 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8236 ainfo->num_attrs = len;
8237 ainfo->image = image;
8238 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8239 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8240 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8241 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8242 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8243 mtoken |= MONO_TOKEN_METHOD_DEF;
8245 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8246 mtoken |= MONO_TOKEN_MEMBER_REF;
8249 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8252 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8253 if (!ainfo->attrs [i].ctor) {
8254 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8259 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8260 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8261 ainfo->attrs [i].data = (guchar*)data;
8269 mono_custom_attrs_from_method (MonoMethod *method)
8274 * An instantiated method has the same cattrs as the generic method definition.
8276 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8277 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8279 if (method->is_inflated)
8280 method = ((MonoMethodInflated *) method)->declaring;
8282 if (method->dynamic || method->klass->image->dynamic)
8283 return lookup_custom_attr (method->klass->image, method);
8286 /* Synthetic methods */
8289 idx = mono_method_get_index (method);
8290 idx <<= MONO_CUSTOM_ATTR_BITS;
8291 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8292 return mono_custom_attrs_from_index (method->klass->image, idx);
8296 mono_custom_attrs_from_class (MonoClass *klass)
8300 if (klass->generic_class)
8301 klass = klass->generic_class->container_class;
8303 if (klass->image->dynamic)
8304 return lookup_custom_attr (klass->image, klass);
8306 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8307 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8308 idx <<= MONO_CUSTOM_ATTR_BITS;
8309 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8311 idx = mono_metadata_token_index (klass->type_token);
8312 idx <<= MONO_CUSTOM_ATTR_BITS;
8313 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8315 return mono_custom_attrs_from_index (klass->image, idx);
8319 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8323 if (assembly->image->dynamic)
8324 return lookup_custom_attr (assembly->image, assembly);
8325 idx = 1; /* there is only one assembly */
8326 idx <<= MONO_CUSTOM_ATTR_BITS;
8327 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8328 return mono_custom_attrs_from_index (assembly->image, idx);
8331 static MonoCustomAttrInfo*
8332 mono_custom_attrs_from_module (MonoImage *image)
8337 return lookup_custom_attr (image, image);
8338 idx = 1; /* there is only one module */
8339 idx <<= MONO_CUSTOM_ATTR_BITS;
8340 idx |= MONO_CUSTOM_ATTR_MODULE;
8341 return mono_custom_attrs_from_index (image, idx);
8345 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8349 if (klass->image->dynamic) {
8350 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8351 return lookup_custom_attr (klass->image, property);
8353 idx = find_property_index (klass, property);
8354 idx <<= MONO_CUSTOM_ATTR_BITS;
8355 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8356 return mono_custom_attrs_from_index (klass->image, idx);
8360 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8364 if (klass->image->dynamic) {
8365 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8366 return lookup_custom_attr (klass->image, event);
8368 idx = find_event_index (klass, event);
8369 idx <<= MONO_CUSTOM_ATTR_BITS;
8370 idx |= MONO_CUSTOM_ATTR_EVENT;
8371 return mono_custom_attrs_from_index (klass->image, idx);
8375 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8378 if (klass->image->dynamic) {
8379 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8380 return lookup_custom_attr (klass->image, field);
8382 idx = find_field_index (klass, field);
8383 idx <<= MONO_CUSTOM_ATTR_BITS;
8384 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8385 return mono_custom_attrs_from_index (klass->image, idx);
8389 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8392 guint32 i, idx, method_index;
8393 guint32 param_list, param_last, param_pos, found;
8395 MonoReflectionMethodAux *aux;
8398 * An instantiated method has the same cattrs as the generic method definition.
8400 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8401 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8403 if (method->is_inflated)
8404 method = ((MonoMethodInflated *) method)->declaring;
8406 if (method->klass->image->dynamic) {
8407 MonoCustomAttrInfo *res, *ainfo;
8410 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8411 if (!aux || !aux->param_cattr)
8414 /* Need to copy since it will be freed later */
8415 ainfo = aux->param_cattr [param];
8416 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8417 res = g_malloc0 (size);
8418 memcpy (res, ainfo, size);
8422 image = method->klass->image;
8423 method_index = mono_method_get_index (method);
8424 ca = &image->tables [MONO_TABLE_METHOD];
8426 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8427 if (method_index == ca->rows) {
8428 ca = &image->tables [MONO_TABLE_PARAM];
8429 param_last = ca->rows + 1;
8431 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8432 ca = &image->tables [MONO_TABLE_PARAM];
8435 for (i = param_list; i < param_last; ++i) {
8436 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8437 if (param_pos == param) {
8445 idx <<= MONO_CUSTOM_ATTR_BITS;
8446 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8447 return mono_custom_attrs_from_index (image, idx);
8451 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8455 for (i = 0; i < ainfo->num_attrs; ++i) {
8456 klass = ainfo->attrs [i].ctor->klass;
8457 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8464 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8471 for (i = 0; i < ainfo->num_attrs; ++i) {
8472 klass = ainfo->attrs [i].ctor->klass;
8473 if (mono_class_has_parent (klass, attr_klass)) {
8478 if (attr_index == -1)
8481 attrs = mono_custom_attrs_construct (ainfo);
8483 return mono_array_get (attrs, MonoObject*, attr_index);
8489 * mono_reflection_get_custom_attrs_info:
8490 * @obj: a reflection object handle
8492 * Return the custom attribute info for attributes defined for the
8493 * reflection handle @obj. The objects.
8495 * FIXME this function leaks like a sieve for SRE objects.
8498 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8501 MonoCustomAttrInfo *cinfo = NULL;
8503 klass = obj->vtable->klass;
8504 if (klass == mono_defaults.monotype_class) {
8505 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8506 klass = mono_class_from_mono_type (type);
8507 cinfo = mono_custom_attrs_from_class (klass);
8508 } else if (strcmp ("Assembly", klass->name) == 0) {
8509 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8510 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8511 } else if (strcmp ("Module", klass->name) == 0) {
8512 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8513 cinfo = mono_custom_attrs_from_module (module->image);
8514 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8515 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8516 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8517 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8518 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8519 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8520 } else if (strcmp ("MonoField", klass->name) == 0) {
8521 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8522 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8523 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8524 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8525 cinfo = mono_custom_attrs_from_method (rmethod->method);
8526 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8527 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8528 cinfo = mono_custom_attrs_from_method (rmethod->method);
8529 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8530 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8531 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8532 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8533 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8534 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8535 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8536 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8537 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8538 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8539 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8540 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8541 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8542 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8543 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8544 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8545 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8546 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8547 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8548 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8549 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8550 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8551 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8552 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8553 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8554 } else { /* handle other types here... */
8555 g_error ("get custom attrs not yet supported for %s", klass->name);
8562 * mono_reflection_get_custom_attrs_by_type:
8563 * @obj: a reflection object handle
8565 * Return an array with all the custom attributes defined of the
8566 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8567 * of that type are returned. The objects are fully build. Return NULL if a loading error
8571 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8574 MonoCustomAttrInfo *cinfo;
8576 cinfo = mono_reflection_get_custom_attrs_info (obj);
8579 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8581 result = mono_custom_attrs_construct (cinfo);
8583 mono_custom_attrs_free (cinfo);
8585 if (mono_loader_get_last_error ())
8587 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8594 * mono_reflection_get_custom_attrs:
8595 * @obj: a reflection object handle
8597 * Return an array with all the custom attributes defined of the
8598 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8602 mono_reflection_get_custom_attrs (MonoObject *obj)
8604 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8608 * mono_reflection_get_custom_attrs_data:
8609 * @obj: a reflection obj handle
8611 * Returns an array of System.Reflection.CustomAttributeData,
8612 * which include information about attributes reflected on
8613 * types loaded using the Reflection Only methods
8616 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8619 MonoCustomAttrInfo *cinfo;
8621 cinfo = mono_reflection_get_custom_attrs_info (obj);
8623 result = mono_custom_attrs_data_construct (cinfo);
8625 mono_custom_attrs_free (cinfo);
8627 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8632 static MonoReflectionType*
8633 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8635 MonoMethod *method_get_underlying_system_type;
8637 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8638 mono_class_get_method_from_name (mono_object_class (t),
8639 "get_UnderlyingSystemType",
8641 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8644 #ifndef DISABLE_REFLECTION_EMIT
8647 is_corlib_type (MonoClass *class)
8649 return class->image == mono_defaults.corlib;
8653 is_usertype (MonoReflectionType *ref)
8655 MonoClass *class = mono_object_class (ref);
8656 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8659 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8660 static MonoClass *cached_class; \
8662 return cached_class == _class; \
8663 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8664 cached_class = _class; \
8671 is_sre_array (MonoClass *class)
8673 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8677 is_sre_byref (MonoClass *class)
8679 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8683 is_sre_pointer (MonoClass *class)
8685 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8689 is_sre_generic_instance (MonoClass *class)
8691 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8695 mono_reflection_type_get_handle (MonoReflectionType* ref)
8703 if (is_usertype (ref)) {
8704 ref = mono_reflection_type_get_underlying_system_type (ref);
8705 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8710 class = mono_object_class (ref);
8712 if (is_sre_array (class)) {
8714 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8715 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8717 if (sre_array->rank == 0) //single dimentional array
8718 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8720 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8721 sre_array->type.type = res;
8723 } else if (is_sre_byref (class)) {
8725 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8726 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8728 res = &mono_class_from_mono_type (base)->this_arg;
8729 sre_byref->type.type = res;
8731 } else if (is_sre_pointer (class)) {
8733 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8734 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8736 res = &mono_ptr_class_get (base)->byval_arg;
8737 sre_pointer->type.type = res;
8739 } else if (is_sre_generic_instance (class)) {
8740 MonoType *res, **types;
8741 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8744 count = mono_array_length (gclass->type_arguments);
8745 types = g_new0 (MonoType*, count);
8746 for (i = 0; i < count; ++i) {
8747 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8748 types [i] = mono_reflection_type_get_handle (t);
8751 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8754 gclass->type.type = res;
8758 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8762 static MonoReflectionType*
8763 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8765 if (!type || type->type)
8768 if (is_usertype (type)) {
8769 type = mono_reflection_type_get_underlying_system_type (type);
8770 if (is_usertype (type))
8771 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8778 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8780 mono_reflection_type_get_handle (type);
8784 * LOCKING: Assumes the loader lock is held.
8786 static MonoMethodSignature*
8787 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8788 MonoMethodSignature *sig;
8791 count = parameters? mono_array_length (parameters): 0;
8793 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8794 sig->param_count = count;
8795 sig->sentinelpos = -1; /* FIXME */
8796 for (i = 0; i < count; ++i)
8797 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8802 * LOCKING: Assumes the loader lock is held.
8804 static MonoMethodSignature*
8805 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8806 MonoMethodSignature *sig;
8808 sig = parameters_to_signature (image, ctor->parameters);
8809 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8810 sig->ret = &mono_defaults.void_class->byval_arg;
8815 * LOCKING: Assumes the loader lock is held.
8817 static MonoMethodSignature*
8818 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8819 MonoMethodSignature *sig;
8821 sig = parameters_to_signature (image, method->parameters);
8822 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8823 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8824 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8828 static MonoMethodSignature*
8829 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8830 MonoMethodSignature *sig;
8832 sig = parameters_to_signature (NULL, method->parameters);
8833 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8834 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8835 sig->generic_param_count = 0;
8840 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8842 MonoClass *klass = mono_object_class (prop);
8843 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8844 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8845 *name = mono_string_to_utf8 (pb->name);
8846 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8848 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8849 *name = g_strdup (p->property->name);
8850 if (p->property->get)
8851 *type = mono_method_signature (p->property->get)->ret;
8853 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8858 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8860 MonoClass *klass = mono_object_class (field);
8861 if (strcmp (klass->name, "FieldBuilder") == 0) {
8862 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8863 *name = mono_string_to_utf8 (fb->name);
8864 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8866 MonoReflectionField *f = (MonoReflectionField *)field;
8867 *name = g_strdup (mono_field_get_name (f->field));
8868 *type = f->field->type;
8871 #endif /* !DISABLE_REFLECTION_EMIT */
8874 * Encode a value in a custom attribute stream of bytes.
8875 * The value to encode is either supplied as an object in argument val
8876 * (valuetypes are boxed), or as a pointer to the data in the
8878 * @type represents the type of the value
8879 * @buffer is the start of the buffer
8880 * @p the current position in the buffer
8881 * @buflen contains the size of the buffer and is used to return the new buffer size
8882 * if this needs to be realloced.
8883 * @retbuffer and @retp return the start and the position of the buffer
8886 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8888 MonoTypeEnum simple_type;
8890 if ((p-buffer) + 10 >= *buflen) {
8893 newbuf = g_realloc (buffer, *buflen);
8894 p = newbuf + (p-buffer);
8898 argval = ((char*)arg + sizeof (MonoObject));
8899 simple_type = type->type;
8901 switch (simple_type) {
8902 case MONO_TYPE_BOOLEAN:
8907 case MONO_TYPE_CHAR:
8910 swap_with_size (p, argval, 2, 1);
8916 swap_with_size (p, argval, 4, 1);
8920 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8930 swap_with_size (p, argval, 8, 1);
8936 swap_with_size (p, argval, 8, 1);
8939 case MONO_TYPE_VALUETYPE:
8940 if (type->data.klass->enumtype) {
8941 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8944 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8947 case MONO_TYPE_STRING: {
8954 str = mono_string_to_utf8 ((MonoString*)arg);
8955 slen = strlen (str);
8956 if ((p-buffer) + 10 + slen >= *buflen) {
8960 newbuf = g_realloc (buffer, *buflen);
8961 p = newbuf + (p-buffer);
8964 mono_metadata_encode_value (slen, p, &p);
8965 memcpy (p, str, slen);
8970 case MONO_TYPE_CLASS: {
8978 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8979 slen = strlen (str);
8980 if ((p-buffer) + 10 + slen >= *buflen) {
8984 newbuf = g_realloc (buffer, *buflen);
8985 p = newbuf + (p-buffer);
8988 mono_metadata_encode_value (slen, p, &p);
8989 memcpy (p, str, slen);
8994 case MONO_TYPE_SZARRAY: {
8996 MonoClass *eclass, *arg_eclass;
8999 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9002 len = mono_array_length ((MonoArray*)arg);
9004 *p++ = (len >> 8) & 0xff;
9005 *p++ = (len >> 16) & 0xff;
9006 *p++ = (len >> 24) & 0xff;
9008 *retbuffer = buffer;
9009 eclass = type->data.klass;
9010 arg_eclass = mono_object_class (arg)->element_class;
9013 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9014 eclass = mono_defaults.object_class;
9016 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9017 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9018 int elsize = mono_class_array_element_size (arg_eclass);
9019 for (i = 0; i < len; ++i) {
9020 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9023 } else if (eclass->valuetype && arg_eclass->valuetype) {
9024 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9025 int elsize = mono_class_array_element_size (eclass);
9026 for (i = 0; i < len; ++i) {
9027 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9031 for (i = 0; i < len; ++i) {
9032 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9037 case MONO_TYPE_OBJECT: {
9043 * The parameter type is 'object' but the type of the actual
9044 * argument is not. So we have to add type information to the blob
9045 * too. This is completely undocumented in the spec.
9049 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9054 klass = mono_object_class (arg);
9056 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9059 } else if (klass->enumtype) {
9061 } else if (klass == mono_defaults.string_class) {
9062 simple_type = MONO_TYPE_STRING;
9065 } else if (klass->rank == 1) {
9067 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9068 /* See Partition II, Appendix B3 */
9071 *p++ = klass->element_class->byval_arg.type;
9072 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9074 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9075 *p++ = simple_type = klass->byval_arg.type;
9078 g_error ("unhandled type in custom attr");
9080 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9081 slen = strlen (str);
9082 if ((p-buffer) + 10 + slen >= *buflen) {
9086 newbuf = g_realloc (buffer, *buflen);
9087 p = newbuf + (p-buffer);
9090 mono_metadata_encode_value (slen, p, &p);
9091 memcpy (p, str, slen);
9094 simple_type = mono_class_enum_basetype (klass)->type;
9098 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9101 *retbuffer = buffer;
9105 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9107 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9108 char *str = type_get_qualified_name (type, NULL);
9109 int slen = strlen (str);
9113 * This seems to be optional...
9116 mono_metadata_encode_value (slen, p, &p);
9117 memcpy (p, str, slen);
9120 } else if (type->type == MONO_TYPE_OBJECT) {
9122 } else if (type->type == MONO_TYPE_CLASS) {
9123 /* it should be a type: encode_cattr_value () has the check */
9126 mono_metadata_encode_value (type->type, p, &p);
9127 if (type->type == MONO_TYPE_SZARRAY)
9128 /* See the examples in Partition VI, Annex B */
9129 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9135 #ifndef DISABLE_REFLECTION_EMIT
9137 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9140 /* Preallocate a large enough buffer */
9141 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9142 char *str = type_get_qualified_name (type, NULL);
9145 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9146 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9152 len += strlen (name);
9154 if ((p-buffer) + 20 + len >= *buflen) {
9158 newbuf = g_realloc (buffer, *buflen);
9159 p = newbuf + (p-buffer);
9163 encode_field_or_prop_type (type, p, &p);
9165 len = strlen (name);
9166 mono_metadata_encode_value (len, p, &p);
9167 memcpy (p, name, len);
9169 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9171 *retbuffer = buffer;
9175 * mono_reflection_get_custom_attrs_blob:
9176 * @ctor: custom attribute constructor
9177 * @ctorArgs: arguments o the constructor
9183 * Creates the blob of data that needs to be saved in the metadata and that represents
9184 * the custom attributed described by @ctor, @ctorArgs etc.
9185 * Returns: a Byte array representing the blob of data.
9188 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9191 MonoMethodSignature *sig;
9196 MONO_ARCH_SAVE_REGS;
9198 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9199 /* sig is freed later so allocate it in the heap */
9200 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9202 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9205 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9207 p = buffer = g_malloc (buflen);
9208 /* write the prolog */
9211 for (i = 0; i < sig->param_count; ++i) {
9212 arg = mono_array_get (ctorArgs, MonoObject*, i);
9213 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9217 i += mono_array_length (properties);
9219 i += mono_array_length (fields);
9221 *p++ = (i >> 8) & 0xff;
9224 for (i = 0; i < mono_array_length (properties); ++i) {
9228 prop = mono_array_get (properties, gpointer, i);
9229 get_prop_name_and_type (prop, &pname, &ptype);
9230 *p++ = 0x54; /* PROPERTY signature */
9231 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9238 for (i = 0; i < mono_array_length (fields); ++i) {
9242 field = mono_array_get (fields, gpointer, i);
9243 get_field_name_and_type (field, &fname, &ftype);
9244 *p++ = 0x53; /* FIELD signature */
9245 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9250 g_assert (p - buffer <= buflen);
9251 buflen = p - buffer;
9252 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9253 p = mono_array_addr (result, char, 0);
9254 memcpy (p, buffer, buflen);
9256 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9262 * mono_reflection_setup_internal_class:
9263 * @tb: a TypeBuilder object
9265 * Creates a MonoClass that represents the TypeBuilder.
9266 * This is a trick that lets us simplify a lot of reflection code
9267 * (and will allow us to support Build and Run assemblies easier).
9270 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9272 MonoClass *klass, *parent;
9274 MONO_ARCH_SAVE_REGS;
9276 RESOLVE_TYPE (tb->parent);
9278 mono_loader_lock ();
9281 /* check so we can compile corlib correctly */
9282 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9283 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9284 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9286 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9292 /* the type has already being created: it means we just have to change the parent */
9293 if (tb->type.type) {
9294 klass = mono_class_from_mono_type (tb->type.type);
9295 klass->parent = NULL;
9296 /* fool mono_class_setup_parent */
9297 klass->supertypes = NULL;
9298 mono_class_setup_parent (klass, parent);
9299 mono_class_setup_mono_type (klass);
9300 mono_loader_unlock ();
9304 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9306 klass->image = &tb->module->dynamic_image->image;
9308 klass->inited = 1; /* we lie to the runtime */
9309 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9310 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9311 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9312 klass->flags = tb->attrs;
9314 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9316 klass->element_class = klass;
9318 if (klass->reflection_info == NULL) {
9320 MOVING_GC_REGISTER (&klass->reflection_info);
9321 klass->reflection_info = tb;
9323 /* Put into cache so mono_class_get () will find it.
9324 Skip nested types as those should not be available on the global scope. */
9325 if (!tb->nesting_type)
9326 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9328 g_assert (klass->reflection_info == tb);
9331 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9332 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9334 if (parent != NULL) {
9335 mono_class_setup_parent (klass, parent);
9336 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9337 const char *old_n = klass->name;
9338 /* trick to get relative numbering right when compiling corlib */
9339 klass->name = "BuildingObject";
9340 mono_class_setup_parent (klass, mono_defaults.object_class);
9341 klass->name = old_n;
9344 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9345 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9346 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9347 klass->instance_size = sizeof (MonoObject);
9348 klass->size_inited = 1;
9349 mono_class_setup_vtable_general (klass, NULL, 0);
9352 mono_class_setup_mono_type (klass);
9354 mono_class_setup_supertypes (klass);
9357 * FIXME: handle interfaces.
9360 tb->type.type = &klass->byval_arg;
9362 if (tb->nesting_type) {
9363 g_assert (tb->nesting_type->type);
9364 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9367 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9369 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9371 mono_loader_unlock ();
9375 * mono_reflection_setup_generic_class:
9376 * @tb: a TypeBuilder object
9378 * Setup the generic class before adding the first generic parameter.
9381 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9386 * mono_reflection_create_generic_class:
9387 * @tb: a TypeBuilder object
9389 * Creates the generic class after all generic parameters have been added.
9392 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9397 MONO_ARCH_SAVE_REGS;
9399 klass = mono_class_from_mono_type (tb->type.type);
9401 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9403 if (klass->generic_container || (count == 0))
9406 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9408 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9410 klass->generic_container->owner.klass = klass;
9411 klass->generic_container->type_argc = count;
9412 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9414 klass->is_generic = 1;
9416 for (i = 0; i < count; i++) {
9417 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9418 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9419 klass->generic_container->type_params [i] = *param;
9420 /*Make sure we are a diferent type instance */
9421 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9422 klass->generic_container->type_params [i].info.pklass = NULL;
9424 g_assert (klass->generic_container->type_params [i].param.owner);
9427 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9431 * mono_reflection_create_internal_class:
9432 * @tb: a TypeBuilder object
9434 * Actually create the MonoClass that is associated with the TypeBuilder.
9437 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9441 MONO_ARCH_SAVE_REGS;
9443 klass = mono_class_from_mono_type (tb->type.type);
9445 mono_loader_lock ();
9446 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9447 MonoReflectionFieldBuilder *fb;
9449 MonoType *enum_basetype;
9451 g_assert (tb->fields != NULL);
9452 g_assert (mono_array_length (tb->fields) >= 1);
9454 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9456 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9457 mono_loader_unlock ();
9461 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9462 klass->element_class = mono_class_from_mono_type (enum_basetype);
9463 if (!klass->element_class)
9464 klass->element_class = mono_class_from_mono_type (enum_basetype);
9467 * get the element_class from the current corlib.
9469 ec = default_class_from_mono_type (enum_basetype);
9470 klass->instance_size = ec->instance_size;
9471 klass->size_inited = 1;
9473 * this is almost safe to do with enums and it's needed to be able
9474 * to create objects of the enum type (for use in SetConstant).
9476 /* FIXME: Does this mean enums can't have method overrides ? */
9477 mono_class_setup_vtable_general (klass, NULL, 0);
9479 mono_loader_unlock ();
9482 static MonoMarshalSpec*
9483 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9484 MonoReflectionMarshal *minfo)
9486 MonoMarshalSpec *res;
9488 res = image_g_new0 (image, MonoMarshalSpec, 1);
9489 res->native = minfo->type;
9491 switch (minfo->type) {
9492 case MONO_NATIVE_LPARRAY:
9493 res->data.array_data.elem_type = minfo->eltype;
9494 if (minfo->has_size) {
9495 res->data.array_data.param_num = minfo->param_num;
9496 res->data.array_data.num_elem = minfo->count;
9497 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9500 res->data.array_data.param_num = -1;
9501 res->data.array_data.num_elem = -1;
9502 res->data.array_data.elem_mult = -1;
9506 case MONO_NATIVE_BYVALTSTR:
9507 case MONO_NATIVE_BYVALARRAY:
9508 res->data.array_data.num_elem = minfo->count;
9511 case MONO_NATIVE_CUSTOM:
9512 if (minfo->marshaltyperef)
9513 res->data.custom_data.custom_name =
9514 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9516 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9525 #endif /* !DISABLE_REFLECTION_EMIT */
9527 MonoReflectionMarshal*
9528 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9529 MonoMarshalSpec *spec)
9531 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9532 MonoReflectionMarshal *minfo;
9535 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9536 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9537 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9538 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9541 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9542 minfo->type = spec->native;
9544 switch (minfo->type) {
9545 case MONO_NATIVE_LPARRAY:
9546 minfo->eltype = spec->data.array_data.elem_type;
9547 minfo->count = spec->data.array_data.num_elem;
9548 minfo->param_num = spec->data.array_data.param_num;
9551 case MONO_NATIVE_BYVALTSTR:
9552 case MONO_NATIVE_BYVALARRAY:
9553 minfo->count = spec->data.array_data.num_elem;
9556 case MONO_NATIVE_CUSTOM:
9557 if (spec->data.custom_data.custom_name) {
9558 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9560 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9562 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9564 if (spec->data.custom_data.cookie)
9565 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9575 #ifndef DISABLE_REFLECTION_EMIT
9577 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9578 ReflectionMethodBuilder *rmb,
9579 MonoMethodSignature *sig)
9582 MonoMethodNormal *pm;
9583 MonoMarshalSpec **specs;
9584 MonoReflectionMethodAux *method_aux;
9590 * Methods created using a MethodBuilder should have their memory allocated
9591 * inside the image mempool, while dynamic methods should have their memory
9594 dynamic = rmb->refs != NULL;
9595 image = dynamic ? NULL : klass->image;
9598 g_assert (!klass->generic_class);
9600 mono_loader_lock ();
9602 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9603 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9604 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9606 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9608 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9610 pm = (MonoMethodNormal*)m;
9612 m->dynamic = dynamic;
9614 m->flags = rmb->attrs;
9615 m->iflags = rmb->iattrs;
9616 m->name = mono_string_to_utf8_image (image, rmb->name);
9619 m->skip_visibility = rmb->skip_visibility;
9621 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9623 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9624 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9627 m->signature->pinvoke = 1;
9628 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9629 m->signature->pinvoke = 1;
9631 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9633 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9634 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9636 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9638 if (klass->image->dynamic)
9639 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9641 mono_loader_unlock ();
9644 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9645 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9646 MonoMethodHeader *header;
9648 gint32 max_stack, i;
9649 gint32 num_locals = 0;
9650 gint32 num_clauses = 0;
9654 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9655 code_size = rmb->ilgen->code_len;
9656 max_stack = rmb->ilgen->max_stack;
9657 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9658 if (rmb->ilgen->ex_handlers)
9659 num_clauses = method_count_clauses (rmb->ilgen);
9662 code = mono_array_addr (rmb->code, guint8, 0);
9663 code_size = mono_array_length (rmb->code);
9664 /* we probably need to run a verifier on the code... */
9674 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9675 header->code_size = code_size;
9676 header->code = image_g_malloc (image, code_size);
9677 memcpy ((char*)header->code, code, code_size);
9678 header->max_stack = max_stack;
9679 header->init_locals = rmb->init_locals;
9680 header->num_locals = num_locals;
9682 for (i = 0; i < num_locals; ++i) {
9683 MonoReflectionLocalBuilder *lb =
9684 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9686 header->locals [i] = image_g_new0 (image, MonoType, 1);
9687 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9690 header->num_clauses = num_clauses;
9692 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9693 rmb->ilgen, num_clauses);
9696 pm->header = header;
9699 if (rmb->generic_params) {
9700 int count = mono_array_length (rmb->generic_params);
9701 MonoGenericContainer *container;
9703 container = rmb->generic_container;
9705 m->is_generic = TRUE;
9706 mono_method_set_generic_container (m, container);
9708 container->type_argc = count;
9709 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9710 container->owner.method = m;
9712 for (i = 0; i < count; i++) {
9713 MonoReflectionGenericParam *gp =
9714 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9715 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9716 container->type_params [i] = *param;
9719 if (klass->generic_container) {
9720 container->parent = klass->generic_container;
9721 container->context.class_inst = klass->generic_container->context.class_inst;
9723 container->context.method_inst = mono_get_shared_generic_inst (container);
9727 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9731 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9733 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9734 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9735 for (i = 0; i < rmb->nrefs; ++i)
9736 data [i + 1] = rmb->refs [i];
9741 /* Parameter info */
9744 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9745 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9746 for (i = 0; i <= m->signature->param_count; ++i) {
9747 MonoReflectionParamBuilder *pb;
9748 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9749 if ((i > 0) && (pb->attrs)) {
9750 /* Make a copy since it might point to a shared type structure */
9751 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9752 m->signature->params [i - 1]->attrs = pb->attrs;
9755 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9756 MonoDynamicImage *assembly;
9757 guint32 idx, def_type, len;
9761 if (!method_aux->param_defaults) {
9762 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9763 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9765 assembly = (MonoDynamicImage*)klass->image;
9766 idx = encode_constant (assembly, pb->def_value, &def_type);
9767 /* Copy the data from the blob since it might get realloc-ed */
9768 p = assembly->blob.data + idx;
9769 len = mono_metadata_decode_blob_size (p, &p2);
9771 method_aux->param_defaults [i] = image_g_malloc (image, len);
9772 method_aux->param_default_types [i] = def_type;
9773 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9777 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9779 if (!method_aux->param_cattr)
9780 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9781 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9787 /* Parameter marshalling */
9790 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9791 MonoReflectionParamBuilder *pb;
9792 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9793 if (pb->marshal_info) {
9795 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9796 specs [pb->position] =
9797 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9801 if (specs != NULL) {
9803 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9804 method_aux->param_marshall = specs;
9807 if (klass->image->dynamic && method_aux)
9808 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9810 mono_loader_unlock ();
9816 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9818 ReflectionMethodBuilder rmb;
9819 MonoMethodSignature *sig;
9821 mono_loader_lock ();
9822 sig = ctor_builder_to_signature (klass->image, mb);
9823 mono_loader_unlock ();
9825 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9827 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9828 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9830 /* If we are in a generic class, we might be called multiple times from inflate_method */
9831 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9832 /* ilgen is no longer needed */
9840 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9842 ReflectionMethodBuilder rmb;
9843 MonoMethodSignature *sig;
9845 mono_loader_lock ();
9846 sig = method_builder_to_signature (klass->image, mb);
9847 mono_loader_unlock ();
9849 reflection_methodbuilder_from_method_builder (&rmb, mb);
9851 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9852 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9854 /* If we are in a generic class, we might be called multiple times from inflate_method */
9855 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9856 /* ilgen is no longer needed */
9862 static MonoClassField*
9863 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9865 MonoClassField *field;
9868 field = g_new0 (MonoClassField, 1);
9870 field->name = mono_string_to_utf8 (fb->name);
9871 if (fb->attrs || fb->modreq || fb->modopt) {
9872 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9873 field->type->attrs = fb->attrs;
9875 g_assert (klass->image->dynamic);
9876 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9877 g_free (field->type);
9878 field->type = custom;
9880 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9882 if (fb->offset != -1)
9883 field->offset = fb->offset;
9884 field->parent = klass;
9885 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9887 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9894 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9897 MonoReflectionTypeBuilder *tb = NULL;
9898 gboolean is_dynamic = FALSE;
9902 mono_loader_lock ();
9904 domain = mono_object_domain (type);
9906 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9907 tb = (MonoReflectionTypeBuilder *) type;
9910 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9911 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9913 tb = rgi->generic_type;
9917 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9918 if (tb && tb->generic_container)
9919 mono_reflection_create_generic_class (tb);
9921 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9922 if (!klass->generic_container) {
9923 mono_loader_unlock ();
9927 if (klass->wastypebuilder) {
9928 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9933 mono_loader_unlock ();
9935 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9937 return &geninst->byval_arg;
9941 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9943 MonoGenericClass *gclass;
9944 MonoGenericInst *inst;
9946 g_assert (klass->generic_container);
9948 inst = mono_metadata_get_generic_inst (type_argc, types);
9949 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9951 return mono_generic_class_get_class (gclass);
9954 MonoReflectionMethod*
9955 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9958 MonoMethod *method, *inflated;
9959 MonoMethodInflated *imethod;
9960 MonoGenericContext tmp_context;
9961 MonoGenericInst *ginst;
9962 MonoType **type_argv;
9965 MONO_ARCH_SAVE_REGS;
9967 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9968 #ifndef DISABLE_REFLECTION_EMIT
9969 MonoReflectionMethodBuilder *mb = NULL;
9970 MonoReflectionTypeBuilder *tb;
9973 mb = (MonoReflectionMethodBuilder *) rmethod;
9974 tb = (MonoReflectionTypeBuilder *) mb->type;
9975 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9977 method = methodbuilder_to_mono_method (klass, mb);
9979 g_assert_not_reached ();
9983 method = rmethod->method;
9986 klass = method->klass;
9988 if (method->is_inflated)
9989 method = ((MonoMethodInflated *) method)->declaring;
9991 count = mono_method_signature (method)->generic_param_count;
9992 if (count != mono_array_length (types))
9995 type_argv = g_new0 (MonoType *, count);
9996 for (i = 0; i < count; i++) {
9997 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9998 type_argv [i] = mono_reflection_type_get_handle (garg);
10000 ginst = mono_metadata_get_generic_inst (count, type_argv);
10001 g_free (type_argv);
10003 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10004 tmp_context.method_inst = ginst;
10006 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10007 imethod = (MonoMethodInflated *) inflated;
10009 if (method->klass->image->dynamic) {
10010 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10012 * This table maps metadata structures representing inflated methods/fields
10013 * to the reflection objects representing their generic definitions.
10015 mono_loader_lock ();
10016 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10017 mono_loader_unlock ();
10020 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10023 #ifndef DISABLE_REFLECTION_EMIT
10025 static MonoMethod *
10026 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10028 MonoMethodInflated *imethod;
10029 MonoGenericContext *context;
10033 * With generic code sharing the klass might not be inflated.
10034 * This can happen because classes inflated with their own
10035 * type arguments are "normalized" to the uninflated class.
10037 if (!klass->generic_class)
10040 context = mono_class_get_context (klass);
10042 if (klass->method.count) {
10043 /* Find the already created inflated method */
10044 for (i = 0; i < klass->method.count; ++i) {
10045 g_assert (klass->methods [i]->is_inflated);
10046 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10049 g_assert (i < klass->method.count);
10050 imethod = (MonoMethodInflated*)klass->methods [i];
10052 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10055 if (method->is_generic && method->klass->image->dynamic) {
10056 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10058 mono_loader_lock ();
10059 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10060 mono_loader_unlock ();
10062 return (MonoMethod *) imethod;
10065 static MonoMethod *
10066 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
10068 MonoMethod *method;
10071 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
10073 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10074 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10075 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10077 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10078 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10079 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10080 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10081 method = ((MonoReflectionMethod *) obj)->method;
10083 method = NULL; /* prevent compiler warning */
10084 g_error ("can't handle type %s", obj->vtable->klass->name);
10087 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10090 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10092 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10093 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10096 MonoGenericClass *gclass;
10097 MonoDynamicGenericClass *dgclass;
10098 MonoClass *klass, *gklass;
10102 MONO_ARCH_SAVE_REGS;
10104 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10105 klass = mono_class_from_mono_type (gtype);
10106 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10107 gclass = gtype->data.generic_class;
10109 g_assert (gclass->is_dynamic);
10110 dgclass = (MonoDynamicGenericClass *) gclass;
10112 if (dgclass->initialized)
10115 gklass = gclass->container_class;
10116 mono_class_init (gklass);
10118 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10119 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10120 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10121 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10122 dgclass->count_events = events ? mono_array_length (events) : 0;
10124 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10125 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10126 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10127 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10128 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10129 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10130 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10132 for (i = 0; i < dgclass->count_methods; i++) {
10133 MonoObject *obj = mono_array_get (methods, gpointer, i);
10135 dgclass->methods [i] = inflate_method (type, obj);
10138 for (i = 0; i < dgclass->count_ctors; i++) {
10139 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10141 dgclass->ctors [i] = inflate_method (type, obj);
10144 for (i = 0; i < dgclass->count_fields; i++) {
10145 MonoObject *obj = mono_array_get (fields, gpointer, i);
10146 MonoClassField *field, *inflated_field = NULL;
10148 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10149 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10150 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10151 field = ((MonoReflectionField *) obj)->field;
10153 field = NULL; /* prevent compiler warning */
10154 g_assert_not_reached ();
10157 dgclass->fields [i] = *field;
10158 dgclass->fields [i].parent = klass;
10159 dgclass->fields [i].type = mono_class_inflate_generic_type (
10160 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10161 dgclass->field_generic_types [i] = field->type;
10162 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10163 dgclass->field_objects [i] = obj;
10165 if (inflated_field) {
10166 g_free (inflated_field);
10168 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10172 for (i = 0; i < dgclass->count_properties; i++) {
10173 MonoObject *obj = mono_array_get (properties, gpointer, i);
10174 MonoProperty *property = &dgclass->properties [i];
10176 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10177 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10179 property->parent = klass;
10180 property->attrs = pb->attrs;
10181 property->name = mono_string_to_utf8 (pb->name);
10182 if (pb->get_method)
10183 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10184 if (pb->set_method)
10185 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10186 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10187 *property = *((MonoReflectionProperty *) obj)->property;
10188 property->name = g_strdup (property->name);
10191 property->get = inflate_mono_method (klass, property->get, NULL);
10193 property->set = inflate_mono_method (klass, property->set, NULL);
10195 g_assert_not_reached ();
10198 for (i = 0; i < dgclass->count_events; i++) {
10199 MonoObject *obj = mono_array_get (events, gpointer, i);
10200 MonoEvent *event = &dgclass->events [i];
10202 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10203 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10205 event->parent = klass;
10206 event->attrs = eb->attrs;
10207 event->name = mono_string_to_utf8 (eb->name);
10208 if (eb->add_method)
10209 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10210 if (eb->remove_method)
10211 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10212 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10213 *event = *((MonoReflectionMonoEvent *) obj)->event;
10214 event->name = g_strdup (event->name);
10217 event->add = inflate_mono_method (klass, event->add, NULL);
10219 event->remove = inflate_mono_method (klass, event->remove, NULL);
10221 g_assert_not_reached ();
10224 dgclass->initialized = TRUE;
10228 ensure_generic_class_runtime_vtable (MonoClass *klass)
10230 MonoClass *gklass = klass->generic_class->container_class;
10233 if (klass->wastypebuilder)
10236 ensure_runtime_vtable (gklass);
10238 klass->method.count = gklass->method.count;
10239 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10241 for (i = 0; i < klass->method.count; i++) {
10242 klass->methods [i] = mono_class_inflate_generic_method_full (
10243 gklass->methods [i], klass, mono_class_get_context (klass));
10246 klass->interface_count = gklass->interface_count;
10247 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10248 for (i = 0; i < klass->interface_count; ++i) {
10249 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10250 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10251 mono_metadata_free_type (iface_type);
10253 ensure_runtime_vtable (klass->interfaces [i]);
10255 klass->interfaces_inited = 1;
10257 /*We can only finish with this klass once it's parent has as well*/
10258 if (gklass->wastypebuilder)
10259 klass->wastypebuilder = TRUE;
10264 ensure_runtime_vtable (MonoClass *klass)
10266 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10269 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10272 ensure_runtime_vtable (klass->parent);
10275 num = tb->ctors? mono_array_length (tb->ctors): 0;
10276 num += tb->num_methods;
10277 klass->method.count = num;
10278 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10279 num = tb->ctors? mono_array_length (tb->ctors): 0;
10280 for (i = 0; i < num; ++i)
10281 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10282 num = tb->num_methods;
10284 for (i = 0; i < num; ++i)
10285 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10287 if (tb->interfaces) {
10288 klass->interface_count = mono_array_length (tb->interfaces);
10289 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10290 for (i = 0; i < klass->interface_count; ++i) {
10291 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10292 klass->interfaces [i] = mono_class_from_mono_type (iface);
10293 ensure_runtime_vtable (klass->interfaces [i]);
10295 klass->interfaces_inited = 1;
10297 } else if (klass->generic_class){
10298 ensure_generic_class_runtime_vtable (klass);
10301 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10302 for (i = 0; i < klass->method.count; ++i)
10303 klass->methods [i]->slot = i;
10305 mono_class_setup_interface_offsets (klass);
10306 mono_class_setup_interface_id (klass);
10310 * The generic vtable is needed even if image->run is not set since some
10311 * runtime code like ves_icall_Type_GetMethodsByName depends on
10312 * method->slot being defined.
10316 * tb->methods could not be freed since it is used for determining
10317 * overrides during dynamic vtable construction.
10322 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10324 MonoReflectionTypeBuilder *tb;
10328 *num_overrides = 0;
10330 g_assert (klass->image->dynamic);
10332 if (!klass->reflection_info)
10335 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10337 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10341 for (i = 0; i < tb->num_methods; ++i) {
10342 MonoReflectionMethodBuilder *mb =
10343 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10344 if (mb->override_method)
10350 *overrides = g_new0 (MonoMethod*, onum * 2);
10353 for (i = 0; i < tb->num_methods; ++i) {
10354 MonoReflectionMethodBuilder *mb =
10355 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10356 if (mb->override_method) {
10357 (*overrides) [onum * 2] =
10358 mb->override_method->method;
10359 (*overrides) [onum * 2 + 1] =
10362 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10363 g_assert (mb->override_method->method);
10364 g_assert (mb->mhandle);
10371 *num_overrides = onum;
10375 typebuilder_setup_fields (MonoClass *klass)
10377 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10378 MonoReflectionFieldBuilder *fb;
10379 MonoClassField *field;
10380 MonoImage *image = klass->image;
10381 const char *p, *p2;
10383 guint32 len, idx, real_size = 0;
10385 klass->field.count = tb->num_fields;
10386 klass->field.first = 0;
10388 if (tb->class_size) {
10389 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10390 klass->packing_size = tb->packing_size;
10391 real_size = klass->instance_size + tb->class_size;
10394 if (!klass->field.count) {
10395 klass->instance_size = MAX (klass->instance_size, real_size);
10399 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10400 mono_class_alloc_ext (klass);
10401 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10403 for (i = 0; i < klass->field.count; ++i) {
10404 fb = mono_array_get (tb->fields, gpointer, i);
10405 field = &klass->fields [i];
10406 field->name = mono_string_to_utf8_image (image, fb->name);
10408 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10409 field->type->attrs = fb->attrs;
10411 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10413 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10414 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10415 if (fb->offset != -1)
10416 field->offset = fb->offset;
10417 field->parent = klass;
10418 fb->handle = field;
10419 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10421 if (fb->def_value) {
10422 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10423 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10424 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10425 /* Copy the data from the blob since it might get realloc-ed */
10426 p = assembly->blob.data + idx;
10427 len = mono_metadata_decode_blob_size (p, &p2);
10429 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10430 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10434 klass->instance_size = MAX (klass->instance_size, real_size);
10435 mono_class_layout_fields (klass);
10439 typebuilder_setup_properties (MonoClass *klass)
10441 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10442 MonoReflectionPropertyBuilder *pb;
10443 MonoImage *image = klass->image;
10444 MonoProperty *properties;
10448 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10450 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10451 klass->ext->property.first = 0;
10453 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10454 klass->ext->properties = properties;
10455 for (i = 0; i < klass->ext->property.count; ++i) {
10456 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10457 properties [i].parent = klass;
10458 properties [i].attrs = pb->attrs;
10459 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10460 if (pb->get_method)
10461 properties [i].get = pb->get_method->mhandle;
10462 if (pb->set_method)
10463 properties [i].set = pb->set_method->mhandle;
10465 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10469 MonoReflectionEvent *
10470 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10472 MonoEvent *event = g_new0 (MonoEvent, 1);
10476 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10478 event->parent = klass;
10479 event->attrs = eb->attrs;
10480 event->name = mono_string_to_utf8 (eb->name);
10481 if (eb->add_method)
10482 event->add = eb->add_method->mhandle;
10483 if (eb->remove_method)
10484 event->remove = eb->remove_method->mhandle;
10485 if (eb->raise_method)
10486 event->raise = eb->raise_method->mhandle;
10488 if (eb->other_methods) {
10489 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10490 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10491 MonoReflectionMethodBuilder *mb =
10492 mono_array_get (eb->other_methods,
10493 MonoReflectionMethodBuilder*, j);
10494 event->other [j] = mb->mhandle;
10498 return mono_event_get_object (mono_object_domain (tb), klass, event);
10502 typebuilder_setup_events (MonoClass *klass)
10504 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10505 MonoReflectionEventBuilder *eb;
10506 MonoImage *image = klass->image;
10511 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10513 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10514 klass->ext->event.first = 0;
10516 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10517 klass->ext->events = events;
10518 for (i = 0; i < klass->ext->event.count; ++i) {
10519 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10520 events [i].parent = klass;
10521 events [i].attrs = eb->attrs;
10522 events [i].name = mono_string_to_utf8_image (image, eb->name);
10523 if (eb->add_method)
10524 events [i].add = eb->add_method->mhandle;
10525 if (eb->remove_method)
10526 events [i].remove = eb->remove_method->mhandle;
10527 if (eb->raise_method)
10528 events [i].raise = eb->raise_method->mhandle;
10530 if (eb->other_methods) {
10531 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10532 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10533 MonoReflectionMethodBuilder *mb =
10534 mono_array_get (eb->other_methods,
10535 MonoReflectionMethodBuilder*, j);
10536 events [i].other [j] = mb->mhandle;
10539 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10544 remove_instantiations_of (gpointer key,
10546 gpointer user_data)
10548 MonoType *type = (MonoType*)key;
10549 MonoClass *klass = (MonoClass*)user_data;
10551 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10558 check_array_for_usertypes (MonoArray *arr)
10565 for (i = 0; i < mono_array_length (arr); ++i)
10566 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10569 MonoReflectionType*
10570 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10573 MonoDomain* domain;
10574 MonoReflectionType* res;
10577 MONO_ARCH_SAVE_REGS;
10579 domain = mono_object_domain (tb);
10580 klass = mono_class_from_mono_type (tb->type.type);
10583 * Check for user defined Type subclasses.
10585 RESOLVE_TYPE (tb->parent);
10586 check_array_for_usertypes (tb->interfaces);
10588 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10589 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10591 RESOLVE_TYPE (fb->type);
10592 check_array_for_usertypes (fb->modreq);
10593 check_array_for_usertypes (fb->modopt);
10594 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10595 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10600 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10601 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10603 RESOLVE_TYPE (mb->rtype);
10604 check_array_for_usertypes (mb->return_modreq);
10605 check_array_for_usertypes (mb->return_modopt);
10606 check_array_for_usertypes (mb->parameters);
10607 if (mb->param_modreq)
10608 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10609 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10610 if (mb->param_modopt)
10611 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10612 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10617 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10618 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10620 check_array_for_usertypes (mb->parameters);
10621 if (mb->param_modreq)
10622 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10623 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10624 if (mb->param_modopt)
10625 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10626 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10631 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10634 * we need to lock the domain because the lock will be taken inside
10635 * So, we need to keep the locking order correct.
10637 mono_loader_lock ();
10638 mono_domain_lock (domain);
10639 if (klass->wastypebuilder) {
10640 mono_domain_unlock (domain);
10641 mono_loader_unlock ();
10642 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10645 * Fields to set in klass:
10646 * the various flags: delegate/unicode/contextbound etc.
10648 klass->flags = tb->attrs;
10649 klass->has_cctor = 1;
10650 klass->has_finalize = 1;
10653 if (!((MonoDynamicImage*)klass->image)->run) {
10654 if (klass->generic_container) {
10655 /* FIXME: The code below can't handle generic classes */
10656 klass->wastypebuilder = TRUE;
10657 mono_loader_unlock ();
10658 mono_domain_unlock (domain);
10659 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10664 /* enums are done right away */
10665 if (!klass->enumtype)
10666 ensure_runtime_vtable (klass);
10668 if (tb->subtypes) {
10669 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10670 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10671 mono_class_alloc_ext (klass);
10672 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)));
10676 klass->nested_classes_inited = TRUE;
10678 /* fields and object layout */
10679 if (klass->parent) {
10680 if (!klass->parent->size_inited)
10681 mono_class_init (klass->parent);
10682 klass->instance_size = klass->parent->instance_size;
10683 klass->sizes.class_size = 0;
10684 klass->min_align = klass->parent->min_align;
10685 /* if the type has no fields we won't call the field_setup
10686 * routine which sets up klass->has_references.
10688 klass->has_references |= klass->parent->has_references;
10690 klass->instance_size = sizeof (MonoObject);
10691 klass->min_align = 1;
10694 /* FIXME: handle packing_size and instance_size */
10695 typebuilder_setup_fields (klass);
10697 typebuilder_setup_properties (klass);
10699 typebuilder_setup_events (klass);
10701 klass->wastypebuilder = TRUE;
10704 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10705 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10706 * we want to return normal System.MonoType objects, so clear these out from the cache.
10708 if (domain->type_hash && klass->generic_container)
10709 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10711 mono_domain_unlock (domain);
10712 mono_loader_unlock ();
10714 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10715 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10716 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10719 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10720 g_assert (res != (MonoReflectionType*)tb);
10726 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10728 MonoGenericParamFull *param;
10732 MONO_ARCH_SAVE_REGS;
10734 param = g_new0 (MonoGenericParamFull, 1);
10736 if (gparam->mbuilder) {
10737 if (!gparam->mbuilder->generic_container) {
10738 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10739 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10740 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10741 gparam->mbuilder->generic_container->is_method = TRUE;
10743 * Cannot set owner.method, since the MonoMethod is not created yet.
10744 * Set the image field instead, so type_in_image () works.
10746 gparam->mbuilder->generic_container->image = klass->image;
10748 param->param.owner = gparam->mbuilder->generic_container;
10749 } else if (gparam->tbuilder) {
10750 if (!gparam->tbuilder->generic_container) {
10751 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10752 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10753 gparam->tbuilder->generic_container->owner.klass = klass;
10755 param->param.owner = gparam->tbuilder->generic_container;
10758 param->info.name = mono_string_to_utf8 (gparam->name);
10759 param->param.num = gparam->index;
10761 image = &gparam->tbuilder->module->dynamic_image->image;
10762 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10764 gparam->type.type = &pklass->byval_arg;
10766 MOVING_GC_REGISTER (&pklass->reflection_info);
10767 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10768 mono_image_lock (image);
10769 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10770 mono_image_unlock (image);
10774 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10776 MonoReflectionModuleBuilder *module = sig->module;
10777 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10778 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10783 check_array_for_usertypes (sig->arguments);
10785 sigbuffer_init (&buf, 32);
10787 sigbuffer_add_value (&buf, 0x07);
10788 sigbuffer_add_value (&buf, na);
10789 if (assembly != NULL){
10790 for (i = 0; i < na; ++i) {
10791 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10792 encode_reflection_type (assembly, type, &buf);
10796 buflen = buf.p - buf.buf;
10797 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10798 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10799 sigbuffer_free (&buf);
10805 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10807 MonoDynamicImage *assembly = sig->module->dynamic_image;
10808 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10813 check_array_for_usertypes (sig->arguments);
10815 sigbuffer_init (&buf, 32);
10817 sigbuffer_add_value (&buf, 0x06);
10818 for (i = 0; i < na; ++i) {
10819 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10820 encode_reflection_type (assembly, type, &buf);
10823 buflen = buf.p - buf.buf;
10824 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10825 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10826 sigbuffer_free (&buf);
10832 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10834 ReflectionMethodBuilder rmb;
10835 MonoMethodSignature *sig;
10840 sig = dynamic_method_to_signature (mb);
10842 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10845 * Resolve references.
10848 * Every second entry in the refs array is reserved for storing handle_class,
10849 * which is needed by the ldtoken implementation in the JIT.
10851 rmb.nrefs = mb->nrefs;
10852 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10853 for (i = 0; i < mb->nrefs; i += 2) {
10854 MonoClass *handle_class;
10856 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10858 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10859 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10861 * The referenced DynamicMethod should already be created by the managed
10862 * code, except in the case of circular references. In that case, we store
10863 * method in the refs array, and fix it up later when the referenced
10864 * DynamicMethod is created.
10866 if (method->mhandle) {
10867 ref = method->mhandle;
10869 /* FIXME: GC object stored in unmanaged memory */
10872 /* FIXME: GC object stored in unmanaged memory */
10873 method->referenced_by = g_slist_append (method->referenced_by, mb);
10875 handle_class = mono_defaults.methodhandle_class;
10877 MonoException *ex = NULL;
10878 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10880 ex = mono_get_exception_type_load (NULL, NULL);
10881 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10882 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10886 mono_raise_exception (ex);
10891 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10892 rmb.refs [i + 1] = handle_class;
10895 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10897 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10899 /* Fix up refs entries pointing at us */
10900 for (l = mb->referenced_by; l; l = l->next) {
10901 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10902 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10905 g_assert (method->mhandle);
10907 data = (gpointer*)wrapper->method_data;
10908 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10909 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10910 data [i + 1] = mb->mhandle;
10913 g_slist_free (mb->referenced_by);
10917 /* ilgen is no longer needed */
10921 #endif /* DISABLE_REFLECTION_EMIT */
10924 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10929 mono_runtime_free_method (
10930 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10935 * mono_reflection_is_valid_dynamic_token:
10937 * Returns TRUE if token is valid.
10941 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10943 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10946 #ifndef DISABLE_REFLECTION_EMIT
10949 * mono_reflection_lookup_dynamic_token:
10951 * Finish the Builder object pointed to by TOKEN and return the corresponding
10952 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10953 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10956 * LOCKING: Take the loader lock
10959 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10961 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10965 mono_loader_lock ();
10966 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10967 mono_loader_unlock ();
10970 g_error ("Could not find required dynamic token 0x%08x", token);
10976 handle_class = &klass;
10977 return resolve_object (image, obj, handle_class, context);
10981 * ensure_complete_type:
10983 * Ensure that KLASS is completed if it is a dynamic type, or references
10987 ensure_complete_type (MonoClass *klass)
10989 if (klass->image->dynamic && !klass->wastypebuilder) {
10990 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10992 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10994 // Asserting here could break a lot of code
10995 //g_assert (klass->wastypebuilder);
10998 if (klass->generic_class) {
10999 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11002 for (i = 0; i < inst->type_argc; ++i) {
11003 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11009 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11011 gpointer result = NULL;
11013 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11014 result = mono_string_intern ((MonoString*)obj);
11015 *handle_class = mono_defaults.string_class;
11017 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11018 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11020 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11021 result = mono_class_from_mono_type (inflated);
11022 mono_metadata_free_type (inflated);
11024 result = mono_class_from_mono_type (type);
11026 *handle_class = mono_defaults.typehandle_class;
11028 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11029 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11030 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11031 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11032 result = ((MonoReflectionMethod*)obj)->method;
11034 result = mono_class_inflate_generic_method (result, context);
11035 *handle_class = mono_defaults.methodhandle_class;
11037 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11038 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11039 result = mb->mhandle;
11041 /* Type is not yet created */
11042 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11044 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11047 * Hopefully this has been filled in by calling CreateType() on the
11051 * TODO: This won't work if the application finishes another
11052 * TypeBuilder instance instead of this one.
11054 result = mb->mhandle;
11057 result = mono_class_inflate_generic_method (result, context);
11058 *handle_class = mono_defaults.methodhandle_class;
11059 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11060 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11062 result = cb->mhandle;
11064 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11066 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11067 result = cb->mhandle;
11070 result = mono_class_inflate_generic_method (result, context);
11071 *handle_class = mono_defaults.methodhandle_class;
11072 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11073 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11075 ensure_complete_type (field->parent);
11077 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11078 MonoClass *class = mono_class_from_mono_type (inflated);
11079 MonoClassField *inflated_field;
11080 gpointer iter = NULL;
11081 mono_metadata_free_type (inflated);
11082 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11083 if (!strcmp (field->name, inflated_field->name))
11086 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11087 result = inflated_field;
11091 *handle_class = mono_defaults.fieldhandle_class;
11093 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11094 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11095 result = fb->handle;
11098 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11100 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11101 result = fb->handle;
11104 if (fb->handle && fb->handle->parent->generic_container) {
11105 MonoClass *klass = fb->handle->parent;
11106 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11107 MonoClass *inflated = mono_class_from_mono_type (type);
11109 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11111 mono_metadata_free_type (type);
11113 *handle_class = mono_defaults.fieldhandle_class;
11114 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11115 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11116 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11119 klass = type->data.klass;
11120 if (klass->wastypebuilder) {
11121 /* Already created */
11125 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11126 result = type->data.klass;
11129 *handle_class = mono_defaults.typehandle_class;
11130 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11131 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11132 MonoMethodSignature *sig;
11135 if (helper->arguments)
11136 nargs = mono_array_length (helper->arguments);
11140 sig = mono_metadata_signature_alloc (image, nargs);
11141 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11142 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11144 if (helper->call_conv == 0) /* unmanaged */
11145 sig->call_convention = helper->unmanaged_call_conv - 1;
11147 if (helper->call_conv & 0x02)
11148 sig->call_convention = MONO_CALL_VARARG;
11150 sig->call_convention = MONO_CALL_DEFAULT;
11152 sig->param_count = nargs;
11153 /* TODO: Copy type ? */
11154 sig->ret = helper->return_type->type;
11155 for (i = 0; i < nargs; ++i)
11156 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11159 *handle_class = NULL;
11160 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11161 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11162 /* Already created by the managed code */
11163 g_assert (method->mhandle);
11164 result = method->mhandle;
11165 *handle_class = mono_defaults.methodhandle_class;
11166 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11167 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11168 type = mono_class_inflate_generic_type (type, context);
11169 result = mono_class_from_mono_type (type);
11170 *handle_class = mono_defaults.typehandle_class;
11172 mono_metadata_free_type (type);
11173 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11174 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11175 type = mono_class_inflate_generic_type (type, context);
11176 result = mono_class_from_mono_type (type);
11177 *handle_class = mono_defaults.typehandle_class;
11179 mono_metadata_free_type (type);
11180 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11181 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11182 MonoClass *inflated;
11185 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11186 inflated = mono_class_from_mono_type (type);
11188 g_assert (f->fb->handle);
11189 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11191 mono_metadata_free_type (type);
11192 *handle_class = mono_defaults.fieldhandle_class;
11193 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11194 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11195 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11196 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11197 g_assert (c->cb->mhandle);
11198 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11199 *handle_class = mono_defaults.methodhandle_class;
11200 mono_metadata_free_type (type);
11201 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11202 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11203 if (m->method_args) {
11204 result = mono_reflection_method_on_tb_inst_get_handle (m);
11206 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11207 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11208 g_assert (m->mb->mhandle);
11209 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11210 mono_metadata_free_type (type);
11212 *handle_class = mono_defaults.methodhandle_class;
11213 } else if (is_sre_array (mono_object_get_class(obj)) ||
11214 is_sre_byref (mono_object_get_class(obj)) ||
11215 is_sre_pointer (mono_object_get_class(obj))) {
11216 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11217 MonoType *type = mono_reflection_type_get_handle (ref_type);
11218 result = mono_class_from_mono_type (type);
11219 *handle_class = mono_defaults.typehandle_class;
11221 g_print ("%s\n", obj->vtable->klass->name);
11222 g_assert_not_reached ();
11227 #else /* DISABLE_REFLECTION_EMIT */
11230 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11232 g_assert_not_reached ();
11237 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11239 g_assert_not_reached ();
11243 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11245 g_assert_not_reached ();
11249 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11251 g_assert_not_reached ();
11255 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11257 g_assert_not_reached ();
11261 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11263 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11267 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11269 g_assert_not_reached ();
11273 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11275 g_assert_not_reached ();
11278 MonoReflectionModule *
11279 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11281 g_assert_not_reached ();
11286 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11288 g_assert_not_reached ();
11293 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11295 g_assert_not_reached ();
11300 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11301 gboolean create_methodspec, gboolean register_token)
11303 g_assert_not_reached ();
11308 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11313 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11314 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11317 g_assert_not_reached ();
11321 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11324 *num_overrides = 0;
11327 MonoReflectionEvent *
11328 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11330 g_assert_not_reached ();
11334 MonoReflectionType*
11335 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11337 g_assert_not_reached ();
11342 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11344 g_assert_not_reached ();
11348 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11350 g_assert_not_reached ();
11355 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11357 g_assert_not_reached ();
11362 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11367 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11373 mono_reflection_type_get_handle (MonoReflectionType* ref)
11380 #endif /* DISABLE_REFLECTION_EMIT */
11382 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11383 const static guint32 declsec_flags_map[] = {
11384 0x00000000, /* empty */
11385 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11386 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11387 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11388 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11389 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11390 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11391 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11392 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11393 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11394 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11395 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11396 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11397 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11398 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11399 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11400 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11401 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11402 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11406 * Returns flags that includes all available security action associated to the handle.
11407 * @token: metadata token (either for a class or a method)
11408 * @image: image where resides the metadata.
11411 mono_declsec_get_flags (MonoImage *image, guint32 token)
11413 int index = mono_metadata_declsec_from_index (image, token);
11414 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11415 guint32 result = 0;
11419 /* HasSecurity can be present for other, not specially encoded, attributes,
11420 e.g. SuppressUnmanagedCodeSecurityAttribute */
11424 for (i = index; i < t->rows; i++) {
11425 guint32 cols [MONO_DECL_SECURITY_SIZE];
11427 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11428 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11431 action = cols [MONO_DECL_SECURITY_ACTION];
11432 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11433 result |= declsec_flags_map [action];
11435 g_assert_not_reached ();
11442 * Get the security actions (in the form of flags) associated with the specified method.
11444 * @method: The method for which we want the declarative security flags.
11445 * Return the declarative security flags for the method (only).
11447 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11448 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11451 mono_declsec_flags_from_method (MonoMethod *method)
11453 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11454 /* FIXME: No cache (for the moment) */
11455 guint32 idx = mono_method_get_index (method);
11456 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11457 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11458 return mono_declsec_get_flags (method->klass->image, idx);
11464 * Get the security actions (in the form of flags) associated with the specified class.
11466 * @klass: The class for which we want the declarative security flags.
11467 * Return the declarative security flags for the class.
11469 * Note: We cache the flags inside the MonoClass structure as this will get
11470 * called very often (at least for each method).
11473 mono_declsec_flags_from_class (MonoClass *klass)
11475 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11476 if (!klass->ext || !klass->ext->declsec_flags) {
11479 idx = mono_metadata_token_index (klass->type_token);
11480 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11481 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11482 mono_loader_lock ();
11483 mono_class_alloc_ext (klass);
11484 mono_loader_unlock ();
11485 /* we cache the flags on classes */
11486 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11488 return klass->ext->declsec_flags;
11494 * Get the security actions (in the form of flags) associated with the specified assembly.
11496 * @assembly: The assembly for which we want the declarative security flags.
11497 * Return the declarative security flags for the assembly.
11500 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11502 guint32 idx = 1; /* there is only one assembly */
11503 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11504 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11505 return mono_declsec_get_flags (assembly->image, idx);
11510 * Fill actions for the specific index (which may either be an encoded class token or
11511 * an encoded method token) from the metadata image.
11512 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11515 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11516 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11518 MonoBoolean result = FALSE;
11520 guint32 cols [MONO_DECL_SECURITY_SIZE];
11521 int index = mono_metadata_declsec_from_index (image, token);
11524 t = &image->tables [MONO_TABLE_DECLSECURITY];
11525 for (i = index; i < t->rows; i++) {
11526 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11528 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11531 /* if present only replace (class) permissions with method permissions */
11532 /* if empty accept either class or method permissions */
11533 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11534 if (!actions->demand.blob) {
11535 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11536 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11537 actions->demand.blob = (char*) (blob + 2);
11538 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11541 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11542 if (!actions->noncasdemand.blob) {
11543 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11544 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11545 actions->noncasdemand.blob = (char*) (blob + 2);
11546 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11549 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11550 if (!actions->demandchoice.blob) {
11551 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11552 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11553 actions->demandchoice.blob = (char*) (blob + 2);
11554 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11564 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11565 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11567 guint32 idx = mono_metadata_token_index (klass->type_token);
11568 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11569 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11570 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11574 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11575 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11577 guint32 idx = mono_method_get_index (method);
11578 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11579 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11580 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11584 * Collect all actions (that requires to generate code in mini) assigned for
11585 * the specified method.
11586 * Note: Don't use the content of actions if the function return FALSE.
11589 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11591 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11592 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11593 MonoBoolean result = FALSE;
11596 /* quick exit if no declarative security is present in the metadata */
11597 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11600 /* we want the original as the wrapper is "free" of the security informations */
11601 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11602 method = mono_marshal_method_from_wrapper (method);
11607 /* First we look for method-level attributes */
11608 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11609 mono_class_init (method->klass);
11610 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11612 result = mono_declsec_get_method_demands_params (method, demands,
11613 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11616 /* Here we use (or create) the class declarative cache to look for demands */
11617 flags = mono_declsec_flags_from_class (method->klass);
11618 if (flags & mask) {
11620 mono_class_init (method->klass);
11621 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11623 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11624 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11627 /* The boolean return value is used as a shortcut in case nothing needs to
11628 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11634 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11636 * Note: Don't use the content of actions if the function return FALSE.
11639 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11641 MonoBoolean result = FALSE;
11644 /* quick exit if no declarative security is present in the metadata */
11645 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11648 /* we want the original as the wrapper is "free" of the security informations */
11649 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11650 method = mono_marshal_method_from_wrapper (method);
11655 /* results are independant - zeroize both */
11656 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11657 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11659 /* First we look for method-level attributes */
11660 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11661 mono_class_init (method->klass);
11663 result = mono_declsec_get_method_demands_params (method, cmethod,
11664 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11667 /* Here we use (or create) the class declarative cache to look for demands */
11668 flags = mono_declsec_flags_from_class (method->klass);
11669 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11670 mono_class_init (method->klass);
11672 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11673 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11680 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11682 * @klass The inherited class - this is the class that provides the security check (attributes)
11684 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11686 * Note: Don't use the content of actions if the function return FALSE.
11689 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11691 MonoBoolean result = FALSE;
11694 /* quick exit if no declarative security is present in the metadata */
11695 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11698 /* Here we use (or create) the class declarative cache to look for demands */
11699 flags = mono_declsec_flags_from_class (klass);
11700 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11701 mono_class_init (klass);
11702 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11704 result |= mono_declsec_get_class_demands_params (klass, demands,
11705 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11712 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11714 * Note: Don't use the content of actions if the function return FALSE.
11717 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11719 /* quick exit if no declarative security is present in the metadata */
11720 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11723 /* we want the original as the wrapper is "free" of the security informations */
11724 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11725 method = mono_marshal_method_from_wrapper (method);
11730 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11731 mono_class_init (method->klass);
11732 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11734 return mono_declsec_get_method_demands_params (method, demands,
11735 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11742 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11744 guint32 cols [MONO_DECL_SECURITY_SIZE];
11748 int index = mono_metadata_declsec_from_index (image, token);
11752 t = &image->tables [MONO_TABLE_DECLSECURITY];
11753 for (i = index; i < t->rows; i++) {
11754 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11756 /* shortcut - index are ordered */
11757 if (token != cols [MONO_DECL_SECURITY_PARENT])
11760 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11761 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11762 entry->blob = (char*) (metadata + 2);
11763 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11772 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11774 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11775 guint32 idx = mono_method_get_index (method);
11776 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11777 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11778 return get_declsec_action (method->klass->image, idx, action, entry);
11784 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11787 guint32 flags = mono_declsec_flags_from_class (klass);
11788 if (declsec_flags_map [action] & flags) {
11789 guint32 idx = mono_metadata_token_index (klass->type_token);
11790 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11791 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11792 return get_declsec_action (klass->image, idx, action, entry);
11798 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11800 guint32 idx = 1; /* there is only one assembly */
11801 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11802 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11804 return get_declsec_action (assembly->image, idx, action, entry);
11808 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11810 MonoObject *res, *exc;
11812 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11813 static MonoMethod *method = NULL;
11815 if (!System_Reflection_Emit_TypeBuilder) {
11816 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11817 g_assert (System_Reflection_Emit_TypeBuilder);
11819 if (method == NULL) {
11820 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11825 * The result of mono_type_get_object () might be a System.MonoType but we
11826 * need a TypeBuilder so use klass->reflection_info.
11828 g_assert (klass->reflection_info);
11829 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11831 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11833 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11837 return *(MonoBoolean*)mono_object_unbox (res);