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)
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) {
1636 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1637 if (type->modifiers [i].required)
1638 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1640 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1641 sigbuffer_add_value (&buf, mono_image_typedef_or_ref (assembly, &class->byval_arg));
1644 encode_type (assembly, type, &buf);
1645 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1646 sigbuffer_free (&buf);
1652 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1657 sigbuffer_init (&buf, 32);
1659 sigbuffer_add_value (&buf, 0x06);
1660 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1661 /* encode custom attributes before the type */
1662 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1663 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1664 sigbuffer_free (&buf);
1669 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1670 char blob_size [64];
1671 char *b = blob_size;
1674 guint32 idx = 0, len = 0, dummy = 0;
1676 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1677 guint32 fpa_double [2];
1682 p = buf = g_malloc (64);
1684 *ret_type = MONO_TYPE_CLASS;
1686 box_val = (char*)&dummy;
1688 box_val = ((char*)val) + sizeof (MonoObject);
1689 *ret_type = val->vtable->klass->byval_arg.type;
1692 switch (*ret_type) {
1693 case MONO_TYPE_BOOLEAN:
1698 case MONO_TYPE_CHAR:
1715 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1716 fpa_p = (guint32*)box_val;
1717 fpa_double [0] = fpa_p [1];
1718 fpa_double [1] = fpa_p [0];
1719 box_val = (char*)fpa_double;
1723 case MONO_TYPE_VALUETYPE:
1724 if (val->vtable->klass->enumtype) {
1725 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1728 g_error ("we can't encode valuetypes");
1729 case MONO_TYPE_CLASS:
1731 case MONO_TYPE_STRING: {
1732 MonoString *str = (MonoString*)val;
1733 /* there is no signature */
1734 len = str->length * 2;
1735 mono_metadata_encode_value (len, b, &b);
1736 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1738 char *swapped = g_malloc (2 * mono_string_length (str));
1739 const char *p = (const char*)mono_string_chars (str);
1741 swap_with_size (swapped, p, 2, mono_string_length (str));
1742 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1746 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1752 case MONO_TYPE_GENERICINST:
1753 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1756 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1759 /* there is no signature */
1760 mono_metadata_encode_value (len, b, &b);
1761 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1762 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1763 swap_with_size (blob_size, box_val, len, 1);
1764 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1766 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1774 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1779 sigbuffer_init (&buf, 32);
1781 sigbuffer_add_value (&buf, minfo->type);
1783 switch (minfo->type) {
1784 case MONO_NATIVE_BYVALTSTR:
1785 case MONO_NATIVE_BYVALARRAY:
1786 sigbuffer_add_value (&buf, minfo->count);
1788 case MONO_NATIVE_LPARRAY:
1789 if (minfo->eltype || minfo->has_size) {
1790 sigbuffer_add_value (&buf, minfo->eltype);
1791 if (minfo->has_size) {
1792 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1793 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1795 /* LAMESPEC: ElemMult is undocumented */
1796 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1800 case MONO_NATIVE_SAFEARRAY:
1802 sigbuffer_add_value (&buf, minfo->eltype);
1804 case MONO_NATIVE_CUSTOM:
1806 str = mono_string_to_utf8 (minfo->guid);
1808 sigbuffer_add_value (&buf, len);
1809 sigbuffer_add_mem (&buf, str, len);
1812 sigbuffer_add_value (&buf, 0);
1814 /* native type name */
1815 sigbuffer_add_value (&buf, 0);
1816 /* custom marshaler type name */
1817 if (minfo->marshaltype || minfo->marshaltyperef) {
1818 if (minfo->marshaltyperef)
1819 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1821 str = mono_string_to_utf8 (minfo->marshaltype);
1823 sigbuffer_add_value (&buf, len);
1824 sigbuffer_add_mem (&buf, str, len);
1827 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1828 sigbuffer_add_value (&buf, 0);
1830 if (minfo->mcookie) {
1831 str = mono_string_to_utf8 (minfo->mcookie);
1833 sigbuffer_add_value (&buf, len);
1834 sigbuffer_add_mem (&buf, str, len);
1837 sigbuffer_add_value (&buf, 0);
1843 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1844 sigbuffer_free (&buf);
1849 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1851 MonoDynamicTable *table;
1854 /* maybe this fixup should be done in the C# code */
1855 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1856 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1857 table = &assembly->tables [MONO_TABLE_FIELD];
1858 fb->table_idx = table->next_idx ++;
1859 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1860 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1861 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1862 values [MONO_FIELD_FLAGS] = fb->attrs;
1863 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1865 if (fb->offset != -1) {
1866 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1868 alloc_table (table, table->rows);
1869 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1870 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1871 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1873 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1874 guint32 field_type = 0;
1875 table = &assembly->tables [MONO_TABLE_CONSTANT];
1877 alloc_table (table, table->rows);
1878 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1879 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1880 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1881 values [MONO_CONSTANT_TYPE] = field_type;
1882 values [MONO_CONSTANT_PADDING] = 0;
1884 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1886 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1888 alloc_table (table, table->rows);
1889 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1890 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1892 * We store it in the code section because it's simpler for now.
1895 if (mono_array_length (fb->rva_data) >= 10)
1896 stream_data_align (&assembly->code);
1897 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1899 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1900 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1902 if (fb->marshal_info) {
1903 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1905 alloc_table (table, table->rows);
1906 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1907 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1908 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1913 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1916 guint32 nparams = 0;
1917 MonoReflectionMethodBuilder *mb = fb->get_method;
1918 MonoReflectionMethodBuilder *smb = fb->set_method;
1921 if (mb && mb->parameters)
1922 nparams = mono_array_length (mb->parameters);
1923 if (!mb && smb && smb->parameters)
1924 nparams = mono_array_length (smb->parameters) - 1;
1925 sigbuffer_init (&buf, 32);
1926 sigbuffer_add_byte (&buf, 0x08);
1927 sigbuffer_add_value (&buf, nparams);
1929 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1930 for (i = 0; i < nparams; ++i) {
1931 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1932 encode_reflection_type (assembly, pt, &buf);
1934 } else if (smb && smb->parameters) {
1935 /* the property type is the last param */
1936 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1937 for (i = 0; i < nparams; ++i) {
1938 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1939 encode_reflection_type (assembly, pt, &buf);
1942 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1945 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1946 sigbuffer_free (&buf);
1951 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1953 MonoDynamicTable *table;
1955 guint num_methods = 0;
1959 * we need to set things in the following tables:
1960 * PROPERTYMAP (info already filled in _get_type_info ())
1961 * PROPERTY (rows already preallocated in _get_type_info ())
1962 * METHOD (method info already done with the generic method code)
1965 table = &assembly->tables [MONO_TABLE_PROPERTY];
1966 pb->table_idx = table->next_idx ++;
1967 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1968 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1969 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1970 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1972 /* FIXME: we still don't handle 'other' methods */
1973 if (pb->get_method) num_methods ++;
1974 if (pb->set_method) num_methods ++;
1976 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1977 table->rows += num_methods;
1978 alloc_table (table, table->rows);
1980 if (pb->get_method) {
1981 semaidx = table->next_idx ++;
1982 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1983 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1984 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1985 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1987 if (pb->set_method) {
1988 semaidx = table->next_idx ++;
1989 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1990 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1991 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1992 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1997 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1999 MonoDynamicTable *table;
2001 guint num_methods = 0;
2005 * we need to set things in the following tables:
2006 * EVENTMAP (info already filled in _get_type_info ())
2007 * EVENT (rows already preallocated in _get_type_info ())
2008 * METHOD (method info already done with the generic method code)
2011 table = &assembly->tables [MONO_TABLE_EVENT];
2012 eb->table_idx = table->next_idx ++;
2013 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2014 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2015 values [MONO_EVENT_FLAGS] = eb->attrs;
2016 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2019 * FIXME: we still don't handle 'other' methods
2021 if (eb->add_method) num_methods ++;
2022 if (eb->remove_method) num_methods ++;
2023 if (eb->raise_method) num_methods ++;
2025 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2026 table->rows += num_methods;
2027 alloc_table (table, table->rows);
2029 if (eb->add_method) {
2030 semaidx = table->next_idx ++;
2031 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2032 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2033 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2034 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2036 if (eb->remove_method) {
2037 semaidx = table->next_idx ++;
2038 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2039 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2040 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2041 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2043 if (eb->raise_method) {
2044 semaidx = table->next_idx ++;
2045 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2046 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2047 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2048 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2053 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2055 MonoDynamicTable *table;
2056 guint32 num_constraints, i;
2060 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2061 num_constraints = gparam->iface_constraints ?
2062 mono_array_length (gparam->iface_constraints) : 0;
2063 table->rows += num_constraints;
2064 if (gparam->base_type)
2066 alloc_table (table, table->rows);
2068 if (gparam->base_type) {
2069 table_idx = table->next_idx ++;
2070 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2072 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2073 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2074 assembly, mono_reflection_type_get_handle (gparam->base_type));
2077 for (i = 0; i < num_constraints; i++) {
2078 MonoReflectionType *constraint = mono_array_get (
2079 gparam->iface_constraints, gpointer, i);
2081 table_idx = table->next_idx ++;
2082 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2084 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2085 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2086 assembly, mono_reflection_type_get_handle (constraint));
2091 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2093 GenericParamTableEntry *entry;
2096 * The GenericParam table must be sorted according to the `owner' field.
2097 * We need to do this sorting prior to writing the GenericParamConstraint
2098 * table, since we have to use the final GenericParam table indices there
2099 * and they must also be sorted.
2102 entry = g_new0 (GenericParamTableEntry, 1);
2103 entry->owner = owner;
2104 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2105 MOVING_GC_REGISTER (&entry->gparam);
2106 entry->gparam = gparam;
2108 g_ptr_array_add (assembly->gen_params, entry);
2112 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2114 MonoDynamicTable *table;
2115 MonoGenericParam *param;
2119 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2120 table_idx = table->next_idx ++;
2121 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2123 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2125 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2126 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2127 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2128 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2130 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2132 encode_constraints (entry->gparam, table_idx, assembly);
2136 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2138 MonoDynamicTable *table;
2141 guint32 cols [MONO_ASSEMBLY_SIZE];
2145 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2148 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2149 table = &assembly->tables [MONO_TABLE_MODULEREF];
2150 token = table->next_idx ++;
2152 alloc_table (table, table->rows);
2153 values = table->values + token * MONO_MODULEREF_SIZE;
2154 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2156 token <<= MONO_RESOLTION_SCOPE_BITS;
2157 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2158 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2163 if (image->assembly->dynamic)
2165 memset (cols, 0, sizeof (cols));
2167 /* image->assembly->image is the manifest module */
2168 image = image->assembly->image;
2169 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2172 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2173 token = table->next_idx ++;
2175 alloc_table (table, table->rows);
2176 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2177 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2178 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2179 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2180 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2181 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2182 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2183 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2184 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2186 if (strcmp ("", image->assembly->aname.culture)) {
2187 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2188 image->assembly->aname.culture);
2191 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2192 guchar pubtoken [9];
2194 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2195 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2197 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2199 token <<= MONO_RESOLTION_SCOPE_BITS;
2200 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2201 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2206 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2208 MonoDynamicTable *table;
2213 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2216 sigbuffer_init (&buf, 32);
2217 switch (type->type) {
2218 case MONO_TYPE_FNPTR:
2220 case MONO_TYPE_SZARRAY:
2221 case MONO_TYPE_ARRAY:
2223 case MONO_TYPE_MVAR:
2224 case MONO_TYPE_GENERICINST:
2225 encode_type (assembly, type, &buf);
2227 case MONO_TYPE_CLASS:
2228 case MONO_TYPE_VALUETYPE: {
2229 MonoClass *k = mono_class_from_mono_type (type);
2230 if (!k || !k->generic_container) {
2231 sigbuffer_free (&buf);
2234 encode_type (assembly, type, &buf);
2238 sigbuffer_free (&buf);
2242 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2243 if (assembly->save) {
2244 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2245 alloc_table (table, table->rows + 1);
2246 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2247 values [MONO_TYPESPEC_SIGNATURE] = token;
2249 sigbuffer_free (&buf);
2251 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2252 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2258 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2260 MonoDynamicTable *table;
2262 guint32 token, scope, enclosing;
2265 /* if the type requires a typespec, we must try that first*/
2266 if (try_typespec && (token = create_typespec (assembly, type)))
2268 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2271 klass = mono_class_from_mono_type (type);
2273 klass = mono_class_from_mono_type (type);
2276 * If it's in the same module and not a generic type parameter:
2278 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2279 (type->type != MONO_TYPE_MVAR)) {
2280 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2281 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2282 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2286 if (klass->nested_in) {
2287 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2288 /* get the typeref idx of the enclosing type */
2289 enclosing >>= MONO_TYPEDEFORREF_BITS;
2290 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2292 scope = resolution_scope_from_image (assembly, klass->image);
2294 table = &assembly->tables [MONO_TABLE_TYPEREF];
2295 if (assembly->save) {
2296 alloc_table (table, table->rows + 1);
2297 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2298 values [MONO_TYPEREF_SCOPE] = scope;
2299 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2300 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2302 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2303 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2305 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2310 * Despite the name, we handle also TypeSpec (with the above helper).
2313 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2315 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2318 #ifndef DISABLE_REFLECTION_EMIT
2320 * Insert a memberef row into the metadata: the token that point to the memberref
2321 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2322 * mono_image_get_fieldref_token()).
2323 * The sig param is an index to an already built signature.
2326 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2328 MonoDynamicTable *table;
2330 guint32 token, pclass;
2333 parent = mono_image_typedef_or_ref (assembly, type);
2334 switch (parent & MONO_TYPEDEFORREF_MASK) {
2335 case MONO_TYPEDEFORREF_TYPEREF:
2336 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2338 case MONO_TYPEDEFORREF_TYPESPEC:
2339 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2341 case MONO_TYPEDEFORREF_TYPEDEF:
2342 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2345 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2348 /* extract the index */
2349 parent >>= MONO_TYPEDEFORREF_BITS;
2351 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2353 if (assembly->save) {
2354 alloc_table (table, table->rows + 1);
2355 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2356 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2357 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2358 values [MONO_MEMBERREF_SIGNATURE] = sig;
2361 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2368 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2371 MonoMethodSignature *sig;
2373 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2375 if (create_typespec) {
2376 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2381 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2382 if (token && !create_typespec)
2385 g_assert (!method->is_inflated);
2388 * A methodref signature can't contain an unmanaged calling convention.
2390 sig = mono_metadata_signature_dup (mono_method_signature (method));
2391 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2392 sig->call_convention = MONO_CALL_DEFAULT;
2393 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2394 method->name, method_encode_signature (assembly, sig));
2396 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2399 if (create_typespec) {
2400 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2401 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2402 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2404 if (assembly->save) {
2407 alloc_table (table, table->rows + 1);
2408 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2409 values [MONO_METHODSPEC_METHOD] = token;
2410 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2413 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2415 /*methodspec and memberef tokens are diferent, */
2416 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2423 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2426 ReflectionMethodBuilder rmb;
2429 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2433 name = mono_string_to_utf8 (method->name);
2434 reflection_methodbuilder_from_method_builder (&rmb, method);
2437 * A methodref signature can't contain an unmanaged calling convention.
2438 * Since some flags are encoded as part of call_conv, we need to check against it.
2440 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2441 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2442 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2443 name, method_builder_encode_signature (assembly, &rmb));
2446 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2451 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2452 const gchar *name, guint32 sig)
2454 MonoDynamicTable *table;
2458 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2460 if (assembly->save) {
2461 alloc_table (table, table->rows + 1);
2462 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2463 values [MONO_MEMBERREF_CLASS] = original;
2464 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2465 values [MONO_MEMBERREF_SIGNATURE] = sig;
2468 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2475 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2479 guint32 nparams = mono_array_length (mb->generic_params);
2482 if (!assembly->save)
2485 sigbuffer_init (&buf, 32);
2487 sigbuffer_add_value (&buf, 0xa);
2488 sigbuffer_add_value (&buf, nparams);
2490 for (i = 0; i < nparams; i++) {
2491 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2492 sigbuffer_add_value (&buf, i);
2495 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2496 sigbuffer_free (&buf);
2501 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2503 MonoDynamicTable *table;
2505 guint32 token, mtoken = 0;
2507 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2511 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2513 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2514 switch (mono_metadata_token_table (mtoken)) {
2515 case MONO_TABLE_MEMBERREF:
2516 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2518 case MONO_TABLE_METHOD:
2519 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2522 g_assert_not_reached ();
2525 if (assembly->save) {
2526 alloc_table (table, table->rows + 1);
2527 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2528 values [MONO_METHODSPEC_METHOD] = mtoken;
2529 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2532 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2535 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2540 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2544 if (mb->generic_params && create_methodspec)
2545 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2547 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2551 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2552 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2557 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2560 ReflectionMethodBuilder rmb;
2563 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2567 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2569 name = mono_string_to_utf8 (rmb.name);
2570 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2571 name, method_builder_encode_signature (assembly, &rmb));
2574 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2580 is_field_on_inst (MonoClassField *field)
2582 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2586 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2589 get_field_on_inst_generic_type (MonoClassField *field)
2591 MonoDynamicGenericClass *dgclass;
2594 g_assert (is_field_on_inst (field));
2596 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2597 field_index = field - dgclass->fields;
2599 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2600 return dgclass->field_generic_types [field_index];
2603 #ifndef DISABLE_REFLECTION_EMIT
2605 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2609 MonoClassField *field;
2611 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2614 g_assert (f->field->parent);
2617 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2618 int index = field - field->parent->fields;
2619 type = field->parent->generic_class->container_class->fields [index].type;
2621 if (is_field_on_inst (f->field))
2622 type = get_field_on_inst_generic_type (f->field);
2624 type = f->field->type;
2626 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2627 mono_field_get_name (f->field),
2628 fieldref_encode_signature (assembly, field->parent->image, type));
2629 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2634 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2638 MonoGenericClass *gclass;
2639 MonoDynamicGenericClass *dgclass;
2640 MonoReflectionFieldBuilder *fb = f->fb;
2644 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2647 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2648 klass = mono_class_from_mono_type (type);
2649 gclass = type->data.generic_class;
2650 g_assert (gclass->is_dynamic);
2651 dgclass = (MonoDynamicGenericClass *) gclass;
2653 name = mono_string_to_utf8 (fb->name);
2654 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2655 field_encode_signature (assembly, fb));
2657 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2662 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2666 MonoGenericClass *gclass;
2667 MonoDynamicGenericClass *dgclass;
2668 MonoReflectionCtorBuilder *cb = c->cb;
2669 ReflectionMethodBuilder rmb;
2673 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2675 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2678 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2679 klass = mono_class_from_mono_type (type);
2680 gclass = type->data.generic_class;
2681 g_assert (gclass->is_dynamic);
2682 dgclass = (MonoDynamicGenericClass *) gclass;
2684 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2686 name = mono_string_to_utf8 (rmb.name);
2688 sig = method_builder_encode_signature (assembly, &rmb);
2690 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2693 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2698 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2701 MonoGenericContext tmp_context;
2702 MonoType **type_argv;
2703 MonoGenericInst *ginst;
2704 MonoMethod *method, *inflated;
2707 method = inflate_method (m->inst, (MonoObject*)m->mb);
2709 klass = method->klass;
2711 if (method->is_inflated)
2712 method = ((MonoMethodInflated *) method)->declaring;
2714 count = mono_array_length (m->method_args);
2716 type_argv = g_new0 (MonoType *, count);
2717 for (i = 0; i < count; i++) {
2718 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2719 type_argv [i] = mono_reflection_type_get_handle (garg);
2721 ginst = mono_metadata_get_generic_inst (count, type_argv);
2724 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2725 tmp_context.method_inst = ginst;
2727 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2732 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2736 MonoGenericClass *gclass;
2737 MonoReflectionMethodBuilder *mb = m->mb;
2738 ReflectionMethodBuilder rmb;
2742 if (m->method_args) {
2743 MonoMethod *inflated;
2745 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2746 if (create_methodspec)
2747 token = mono_image_get_methodspec_token (assembly, inflated);
2749 token = mono_image_get_inflated_method_token (assembly, inflated);
2753 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2756 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2757 klass = mono_class_from_mono_type (type);
2758 gclass = type->data.generic_class;
2759 g_assert (gclass->is_dynamic);
2761 reflection_methodbuilder_from_method_builder (&rmb, mb);
2763 name = mono_string_to_utf8 (rmb.name);
2765 sig = method_builder_encode_signature (assembly, &rmb);
2767 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2770 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2775 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2779 guint32 nparams = context->method_inst->type_argc;
2782 if (!assembly->save)
2785 sigbuffer_init (&buf, 32);
2787 * FIXME: vararg, explicit_this, differenc call_conv values...
2789 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2790 sigbuffer_add_value (&buf, nparams);
2792 for (i = 0; i < nparams; i++)
2793 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2796 sigbuffer_free (&buf);
2801 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2803 MonoDynamicTable *table;
2805 guint32 token, mtoken = 0, sig;
2806 MonoMethodInflated *imethod;
2807 MonoMethod *declaring;
2809 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2811 g_assert (method->is_inflated);
2812 imethod = (MonoMethodInflated *) method;
2813 declaring = imethod->declaring;
2815 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2816 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2818 if (!mono_method_signature (declaring)->generic_param_count)
2821 switch (mono_metadata_token_table (mtoken)) {
2822 case MONO_TABLE_MEMBERREF:
2823 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2825 case MONO_TABLE_METHOD:
2826 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2829 g_assert_not_reached ();
2832 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2834 if (assembly->save) {
2835 alloc_table (table, table->rows + 1);
2836 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2837 values [MONO_METHODSPEC_METHOD] = mtoken;
2838 values [MONO_METHODSPEC_SIGNATURE] = sig;
2841 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2848 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2850 MonoMethodInflated *imethod;
2853 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2857 g_assert (method->is_inflated);
2858 imethod = (MonoMethodInflated *) method;
2860 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2861 token = method_encode_methodspec (assembly, method);
2863 guint32 sig = method_encode_signature (
2864 assembly, mono_method_signature (imethod->declaring));
2865 token = mono_image_get_memberref_token (
2866 assembly, &method->klass->byval_arg, method->name, sig);
2869 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2874 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2876 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2879 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2880 token = mono_image_get_memberref_token (
2881 assembly, &m->klass->byval_arg, m->name, sig);
2887 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2889 MonoDynamicTable *table;
2898 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2899 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2900 * Because of this, we must not insert it into the `typeref' hash table.
2902 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2903 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2907 sigbuffer_init (&buf, 32);
2909 g_assert (tb->generic_params);
2910 klass = mono_class_from_mono_type (type);
2912 if (tb->generic_container)
2913 mono_reflection_create_generic_class (tb);
2915 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2916 g_assert (klass->generic_container);
2917 sigbuffer_add_value (&buf, klass->byval_arg.type);
2918 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2920 count = mono_array_length (tb->generic_params);
2921 sigbuffer_add_value (&buf, count);
2922 for (i = 0; i < count; i++) {
2923 MonoReflectionGenericParam *gparam;
2925 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2927 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
2930 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2932 if (assembly->save) {
2933 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2934 alloc_table (table, table->rows + 1);
2935 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2936 values [MONO_TYPESPEC_SIGNATURE] = token;
2938 sigbuffer_free (&buf);
2940 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2941 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2947 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2950 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2952 int i, count, len, pos;
2957 count += mono_array_length (modreq);
2959 count += mono_array_length (modopt);
2962 return mono_metadata_type_dup (NULL, type);
2964 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
2966 memcpy (t, type, MONO_SIZEOF_TYPE);
2968 t->num_mods = count;
2971 for (i = 0; i < mono_array_length (modreq); ++i) {
2972 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
2973 t->modifiers [pos].required = 1;
2974 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2979 for (i = 0; i < mono_array_length (modopt); ++i) {
2980 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
2981 t->modifiers [pos].required = 0;
2982 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2991 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2993 MonoDynamicTable *table;
2995 MonoType *custom = NULL;
2997 guint32 token, pclass, parent, sig;
3000 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
3004 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3005 name = mono_string_to_utf8 (fb->name);
3007 /* fb->type does not include the custom modifiers */
3008 /* FIXME: We should do this in one place when a fieldbuilder is created */
3009 if (fb->modreq || fb->modopt) {
3010 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3011 sig = fieldref_encode_signature (assembly, (MonoImage*)assembly, custom);
3014 sig = fieldref_encode_signature (assembly, (MonoImage*)assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3017 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3018 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3020 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3021 parent >>= MONO_TYPEDEFORREF_BITS;
3023 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3025 if (assembly->save) {
3026 alloc_table (table, table->rows + 1);
3027 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3028 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3029 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3030 values [MONO_MEMBERREF_SIGNATURE] = sig;
3033 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3035 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3041 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3048 if (!assembly->save)
3051 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3052 g_assert (helper->type == 2);
3054 if (helper->arguments)
3055 nargs = mono_array_length (helper->arguments);
3059 size = 10 + (nargs * 10);
3061 sigbuffer_init (&buf, 32);
3063 /* Encode calling convention */
3064 /* Change Any to Standard */
3065 if ((helper->call_conv & 0x03) == 0x03)
3066 helper->call_conv = 0x01;
3067 /* explicit_this implies has_this */
3068 if (helper->call_conv & 0x40)
3069 helper->call_conv &= 0x20;
3071 if (helper->call_conv == 0) { /* Unmanaged */
3072 idx = helper->unmanaged_call_conv - 1;
3075 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3076 if (helper->call_conv & 0x02) /* varargs */
3080 sigbuffer_add_byte (&buf, idx);
3081 sigbuffer_add_value (&buf, nargs);
3082 encode_reflection_type (assembly, helper->return_type, &buf);
3083 for (i = 0; i < nargs; ++i) {
3084 MonoArray *modreqs = NULL;
3085 MonoArray *modopts = NULL;
3086 MonoReflectionType *pt;
3088 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3089 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3090 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3091 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3093 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3094 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3095 encode_reflection_type (assembly, pt, &buf);
3097 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3098 sigbuffer_free (&buf);
3104 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3107 MonoDynamicTable *table;
3110 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3111 idx = table->next_idx ++;
3113 alloc_table (table, table->rows);
3114 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3116 values [MONO_STAND_ALONE_SIGNATURE] =
3117 mono_reflection_encode_sighelper (assembly, helper);
3123 reflection_cc_to_file (int call_conv) {
3124 switch (call_conv & 0x3) {
3126 case 1: return MONO_CALL_DEFAULT;
3127 case 2: return MONO_CALL_VARARG;
3129 g_assert_not_reached ();
3133 #endif /* !DISABLE_REFLECTION_EMIT */
3137 MonoMethodSignature *sig;
3142 #ifndef DISABLE_REFLECTION_EMIT
3144 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3149 MonoMethodSignature *sig;
3153 name = mono_string_to_utf8 (m->name);
3154 nparams = mono_array_length (m->parameters);
3155 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3157 sig->sentinelpos = -1;
3158 sig->call_convention = reflection_cc_to_file (m->call_conv);
3159 sig->param_count = nparams;
3160 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3161 mtype = mono_reflection_type_get_handle (m->parent);
3162 for (i = 0; i < nparams; ++i)
3163 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3165 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3167 if (strcmp (name, am->name) == 0 &&
3168 mono_metadata_type_equal (am->parent, mtype) &&
3169 mono_metadata_signature_equal (am->sig, sig)) {
3172 m->table_idx = am->token & 0xffffff;
3176 am = g_new0 (ArrayMethod, 1);
3180 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3181 method_encode_signature (assembly, sig));
3182 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3183 m->table_idx = am->token & 0xffffff;
3189 * Insert into the metadata tables all the info about the TypeBuilder tb.
3190 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3193 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3195 MonoDynamicTable *table;
3197 int i, is_object = 0, is_system = 0;
3200 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3201 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3202 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3203 n = mono_string_to_utf8 (tb->name);
3204 if (strcmp (n, "Object") == 0)
3206 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3208 n = mono_string_to_utf8 (tb->nspace);
3209 if (strcmp (n, "System") == 0)
3211 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3213 if (tb->parent && !(is_system && is_object) &&
3214 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3215 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3217 values [MONO_TYPEDEF_EXTENDS] = 0;
3219 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3220 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3223 * if we have explicitlayout or sequentiallayouts, output data in the
3224 * ClassLayout table.
3226 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3227 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3228 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3230 alloc_table (table, table->rows);
3231 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3232 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3233 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3234 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3237 /* handle interfaces */
3238 if (tb->interfaces) {
3239 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3241 table->rows += mono_array_length (tb->interfaces);
3242 alloc_table (table, table->rows);
3243 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3244 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3245 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3246 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3247 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3248 values += MONO_INTERFACEIMPL_SIZE;
3254 table = &assembly->tables [MONO_TABLE_FIELD];
3255 table->rows += tb->num_fields;
3256 alloc_table (table, table->rows);
3257 for (i = 0; i < tb->num_fields; ++i)
3258 mono_image_get_field_info (
3259 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3262 /* handle constructors */
3264 table = &assembly->tables [MONO_TABLE_METHOD];
3265 table->rows += mono_array_length (tb->ctors);
3266 alloc_table (table, table->rows);
3267 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3268 mono_image_get_ctor_info (domain,
3269 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3272 /* handle methods */
3274 table = &assembly->tables [MONO_TABLE_METHOD];
3275 table->rows += tb->num_methods;
3276 alloc_table (table, table->rows);
3277 for (i = 0; i < tb->num_methods; ++i)
3278 mono_image_get_method_info (
3279 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3282 /* Do the same with properties etc.. */
3283 if (tb->events && mono_array_length (tb->events)) {
3284 table = &assembly->tables [MONO_TABLE_EVENT];
3285 table->rows += mono_array_length (tb->events);
3286 alloc_table (table, table->rows);
3287 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3289 alloc_table (table, table->rows);
3290 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3291 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3292 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3293 for (i = 0; i < mono_array_length (tb->events); ++i)
3294 mono_image_get_event_info (
3295 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3297 if (tb->properties && mono_array_length (tb->properties)) {
3298 table = &assembly->tables [MONO_TABLE_PROPERTY];
3299 table->rows += mono_array_length (tb->properties);
3300 alloc_table (table, table->rows);
3301 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3303 alloc_table (table, table->rows);
3304 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3305 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3306 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3307 for (i = 0; i < mono_array_length (tb->properties); ++i)
3308 mono_image_get_property_info (
3309 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3312 /* handle generic parameters */
3313 if (tb->generic_params) {
3314 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3315 table->rows += mono_array_length (tb->generic_params);
3316 alloc_table (table, table->rows);
3317 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3318 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3320 mono_image_get_generic_param_info (
3321 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3325 mono_image_add_decl_security (assembly,
3326 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3329 MonoDynamicTable *ntable;
3331 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3332 ntable->rows += mono_array_length (tb->subtypes);
3333 alloc_table (ntable, ntable->rows);
3334 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3336 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3337 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3339 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3340 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3341 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3342 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3343 mono_string_to_utf8 (tb->name), tb->table_idx,
3344 ntable->next_idx, ntable->rows);*/
3345 values += MONO_NESTED_CLASS_SIZE;
3352 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3356 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3358 if (!type->subtypes)
3361 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3362 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3363 collect_types (types, subtype);
3368 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3370 if ((*type1)->table_idx < (*type2)->table_idx)
3373 if ((*type1)->table_idx > (*type2)->table_idx)
3380 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3385 for (i = 0; i < mono_array_length (pinfo); ++i) {
3386 MonoReflectionParamBuilder *pb;
3387 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3390 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3395 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3398 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3400 for (i = 0; i < tb->num_fields; ++i) {
3401 MonoReflectionFieldBuilder* fb;
3402 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3403 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3407 for (i = 0; i < mono_array_length (tb->events); ++i) {
3408 MonoReflectionEventBuilder* eb;
3409 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3410 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3413 if (tb->properties) {
3414 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3415 MonoReflectionPropertyBuilder* pb;
3416 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3417 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3421 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3422 MonoReflectionCtorBuilder* cb;
3423 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3424 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3425 params_add_cattrs (assembly, cb->pinfo);
3430 for (i = 0; i < tb->num_methods; ++i) {
3431 MonoReflectionMethodBuilder* mb;
3432 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3433 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3434 params_add_cattrs (assembly, mb->pinfo);
3439 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3440 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3445 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3449 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3451 if (moduleb->global_methods) {
3452 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3453 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3454 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3455 params_add_cattrs (assembly, mb->pinfo);
3459 if (moduleb->global_fields) {
3460 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3461 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3462 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3466 if (moduleb->types) {
3467 for (i = 0; i < moduleb->num_types; ++i)
3468 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3473 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3475 MonoDynamicTable *table;
3479 char *b = blob_size;
3482 table = &assembly->tables [MONO_TABLE_FILE];
3484 alloc_table (table, table->rows);
3485 values = table->values + table->next_idx * MONO_FILE_SIZE;
3486 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3487 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3488 if (module->image->dynamic) {
3489 /* This depends on the fact that the main module is emitted last */
3490 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3491 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3494 path = g_strdup (module->image->name);
3496 mono_sha1_get_digest_from_file (path, hash);
3499 mono_metadata_encode_value (20, b, &b);
3500 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3501 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3506 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3508 MonoDynamicTable *table;
3511 table = &assembly->tables [MONO_TABLE_MODULE];
3512 mb->table_idx = table->next_idx ++;
3513 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3514 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3517 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3518 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3519 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3520 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3524 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3525 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3527 MonoDynamicTable *table;
3531 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3532 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3535 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3537 alloc_table (table, table->rows);
3538 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3540 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3541 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3542 if (klass->nested_in)
3543 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3545 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3546 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3547 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3549 res = table->next_idx;
3553 /* Emit nested types */
3554 if (klass->ext && klass->ext->nested_classes) {
3557 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3558 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3565 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3566 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3571 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3573 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3575 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3576 parent_index, assembly);
3580 * We need to do this ourselves since klass->nested_classes is not set up.
3583 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3584 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3589 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3590 guint32 module_index, MonoDynamicImage *assembly)
3592 MonoImage *image = module->image;
3596 t = &image->tables [MONO_TABLE_TYPEDEF];
3598 for (i = 0; i < t->rows; ++i) {
3599 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3601 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3602 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3607 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3609 MonoDynamicTable *table;
3611 guint32 scope, idx, res, impl;
3612 gboolean forwarder = TRUE;
3614 if (klass->nested_in) {
3615 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3618 scope = resolution_scope_from_image (assembly, klass->image);
3619 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3620 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3621 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3624 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3627 alloc_table (table, table->rows);
3628 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3630 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3631 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3632 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3633 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3634 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3636 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3644 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3649 if (!assemblyb->type_forwarders)
3652 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3653 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3658 type = mono_reflection_type_get_handle (t);
3661 klass = mono_class_from_mono_type (type);
3663 add_exported_type (assemblyb, assembly, klass);
3667 #define align_pointer(base,p)\
3669 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3671 (p) += 4 - (__diff & 3);\
3675 compare_constants (const void *a, const void *b)
3677 const guint32 *a_values = a;
3678 const guint32 *b_values = b;
3679 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3683 compare_semantics (const void *a, const void *b)
3685 const guint32 *a_values = a;
3686 const guint32 *b_values = b;
3687 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3690 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3694 compare_custom_attrs (const void *a, const void *b)
3696 const guint32 *a_values = a;
3697 const guint32 *b_values = b;
3699 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3703 compare_field_marshal (const void *a, const void *b)
3705 const guint32 *a_values = a;
3706 const guint32 *b_values = b;
3708 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3712 compare_nested (const void *a, const void *b)
3714 const guint32 *a_values = a;
3715 const guint32 *b_values = b;
3717 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3721 compare_genericparam (const void *a, const void *b)
3723 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3724 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3726 if ((*b_entry)->owner == (*a_entry)->owner)
3728 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3729 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3731 return (*a_entry)->owner - (*b_entry)->owner;
3735 compare_declsecurity_attrs (const void *a, const void *b)
3737 const guint32 *a_values = a;
3738 const guint32 *b_values = b;
3740 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3744 compare_interface_impl (const void *a, const void *b)
3746 const guint32 *a_values = a;
3747 const guint32 *b_values = b;
3749 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3753 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3757 pad_heap (MonoDynamicStream *sh)
3759 if (sh->index & 3) {
3760 int sz = 4 - (sh->index & 3);
3761 memset (sh->data + sh->index, 0, sz);
3768 MonoDynamicStream *stream;
3772 * build_compressed_metadata() fills in the blob of data that represents the
3773 * raw metadata as it will be saved in the PE file. The five streams are output
3774 * and the metadata tables are comnpressed from the guint32 array representation,
3775 * to the compressed on-disk format.
3778 build_compressed_metadata (MonoDynamicImage *assembly)
3780 MonoDynamicTable *table;
3782 guint64 valid_mask = 0;
3783 guint64 sorted_mask;
3784 guint32 heapt_size = 0;
3785 guint32 meta_size = 256; /* allow for header and other stuff */
3786 guint32 table_offset;
3787 guint32 ntables = 0;
3793 struct StreamDesc stream_desc [5];
3795 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3796 for (i = 0; i < assembly->gen_params->len; i++){
3797 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3798 write_generic_param_entry (assembly, entry);
3801 stream_desc [0].name = "#~";
3802 stream_desc [0].stream = &assembly->tstream;
3803 stream_desc [1].name = "#Strings";
3804 stream_desc [1].stream = &assembly->sheap;
3805 stream_desc [2].name = "#US";
3806 stream_desc [2].stream = &assembly->us;
3807 stream_desc [3].name = "#Blob";
3808 stream_desc [3].stream = &assembly->blob;
3809 stream_desc [4].name = "#GUID";
3810 stream_desc [4].stream = &assembly->guid;
3812 /* tables that are sorted */
3813 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3814 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3815 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3816 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3817 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3818 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3819 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3821 /* Compute table sizes */
3822 /* the MonoImage has already been created in mono_image_basic_init() */
3823 meta = &assembly->image;
3825 /* sizes should be multiple of 4 */
3826 pad_heap (&assembly->blob);
3827 pad_heap (&assembly->guid);
3828 pad_heap (&assembly->sheap);
3829 pad_heap (&assembly->us);
3831 /* Setup the info used by compute_sizes () */
3832 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3833 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3834 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3836 meta_size += assembly->blob.index;
3837 meta_size += assembly->guid.index;
3838 meta_size += assembly->sheap.index;
3839 meta_size += assembly->us.index;
3841 for (i=0; i < MONO_TABLE_NUM; ++i)
3842 meta->tables [i].rows = assembly->tables [i].rows;
3844 for (i = 0; i < MONO_TABLE_NUM; i++){
3845 if (meta->tables [i].rows == 0)
3847 valid_mask |= (guint64)1 << i;
3849 meta->tables [i].row_size = mono_metadata_compute_size (
3850 meta, i, &meta->tables [i].size_bitfield);
3851 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3853 heapt_size += 24; /* #~ header size */
3854 heapt_size += ntables * 4;
3855 /* make multiple of 4 */
3858 meta_size += heapt_size;
3859 meta->raw_metadata = g_malloc0 (meta_size);
3860 p = (unsigned char*)meta->raw_metadata;
3861 /* the metadata signature */
3862 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3863 /* version numbers and 4 bytes reserved */
3864 int16val = (guint16*)p;
3865 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3866 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3868 /* version string */
3869 int32val = (guint32*)p;
3870 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3872 memcpy (p, meta->version, strlen (meta->version));
3873 p += GUINT32_FROM_LE (*int32val);
3874 align_pointer (meta->raw_metadata, p);
3875 int16val = (guint16*)p;
3876 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3877 *int16val = GUINT16_TO_LE (5); /* number of streams */
3881 * write the stream info.
3883 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3884 table_offset += 3; table_offset &= ~3;
3886 assembly->tstream.index = heapt_size;
3887 for (i = 0; i < 5; ++i) {
3888 int32val = (guint32*)p;
3889 stream_desc [i].stream->offset = table_offset;
3890 *int32val++ = GUINT32_TO_LE (table_offset);
3891 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3892 table_offset += GUINT32_FROM_LE (*int32val);
3893 table_offset += 3; table_offset &= ~3;
3895 strcpy ((char*)p, stream_desc [i].name);
3896 p += strlen (stream_desc [i].name) + 1;
3897 align_pointer (meta->raw_metadata, p);
3900 * now copy the data, the table stream header and contents goes first.
3902 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3903 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3904 int32val = (guint32*)p;
3905 *int32val = GUINT32_TO_LE (0); /* reserved */
3908 if (mono_framework_version () > 1) {
3909 *p++ = 2; /* version */
3912 *p++ = 1; /* version */
3916 if (meta->idx_string_wide)
3918 if (meta->idx_guid_wide)
3920 if (meta->idx_blob_wide)
3923 *p++ = 1; /* reserved */
3924 int64val = (guint64*)p;
3925 *int64val++ = GUINT64_TO_LE (valid_mask);
3926 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3928 int32val = (guint32*)p;
3929 for (i = 0; i < MONO_TABLE_NUM; i++){
3930 if (meta->tables [i].rows == 0)
3932 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3934 p = (unsigned char*)int32val;
3936 /* sort the tables that still need sorting */
3937 table = &assembly->tables [MONO_TABLE_CONSTANT];
3939 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3940 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3942 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3943 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3945 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3946 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3948 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3949 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3951 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3952 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3953 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3955 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3956 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3958 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3960 /* compress the tables */
3961 for (i = 0; i < MONO_TABLE_NUM; i++){
3964 guint32 bitfield = meta->tables [i].size_bitfield;
3965 if (!meta->tables [i].rows)
3967 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3968 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3969 meta->tables [i].base = (char*)p;
3970 for (row = 1; row <= meta->tables [i].rows; ++row) {
3971 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3972 for (col = 0; col < assembly->tables [i].columns; ++col) {
3973 switch (mono_metadata_table_size (bitfield, col)) {
3975 *p++ = values [col];
3978 *p++ = values [col] & 0xff;
3979 *p++ = (values [col] >> 8) & 0xff;
3982 *p++ = values [col] & 0xff;
3983 *p++ = (values [col] >> 8) & 0xff;
3984 *p++ = (values [col] >> 16) & 0xff;
3985 *p++ = (values [col] >> 24) & 0xff;
3988 g_assert_not_reached ();
3992 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3995 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3996 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3997 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3998 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3999 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4001 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4005 * Some tables in metadata need to be sorted according to some criteria, but
4006 * when methods and fields are first created with reflection, they may be assigned a token
4007 * that doesn't correspond to the final token they will get assigned after the sorting.
4008 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4009 * with the reflection objects that represent them. Once all the tables are set up, the
4010 * reflection objects will contains the correct table index. fixup_method() will fixup the
4011 * tokens for the method with ILGenerator @ilgen.
4014 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4016 guint32 code_idx = GPOINTER_TO_UINT (value);
4017 MonoReflectionILTokenInfo *iltoken;
4018 MonoReflectionFieldBuilder *field;
4019 MonoReflectionCtorBuilder *ctor;
4020 MonoReflectionMethodBuilder *method;
4021 MonoReflectionTypeBuilder *tb;
4022 MonoReflectionArrayMethod *am;
4024 unsigned char *target;
4026 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4027 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4028 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4029 switch (target [3]) {
4030 case MONO_TABLE_FIELD:
4031 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4032 field = (MonoReflectionFieldBuilder *)iltoken->member;
4033 idx = field->table_idx;
4034 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4035 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4036 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4038 g_assert_not_reached ();
4041 case MONO_TABLE_METHOD:
4042 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4043 method = (MonoReflectionMethodBuilder *)iltoken->member;
4044 idx = method->table_idx;
4045 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4046 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4047 idx = ctor->table_idx;
4048 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4049 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4050 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4051 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4053 g_assert_not_reached ();
4056 case MONO_TABLE_TYPEDEF:
4057 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4058 g_assert_not_reached ();
4059 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4060 idx = tb->table_idx;
4062 case MONO_TABLE_MEMBERREF:
4063 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4064 am = (MonoReflectionArrayMethod*)iltoken->member;
4065 idx = am->table_idx;
4066 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4067 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4068 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4069 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4070 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4071 g_assert (m->klass->generic_class || m->klass->generic_container);
4073 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4075 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4076 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4077 g_assert (is_field_on_inst (f));
4079 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4080 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4082 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4084 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4086 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4089 g_assert_not_reached ();
4092 case MONO_TABLE_METHODSPEC:
4093 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4094 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4095 g_assert (mono_method_signature (m)->generic_param_count);
4097 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4099 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4102 g_assert_not_reached ();
4106 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4108 target [0] = idx & 0xff;
4109 target [1] = (idx >> 8) & 0xff;
4110 target [2] = (idx >> 16) & 0xff;
4117 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4118 * value is not known when the table is emitted.
4121 fixup_cattrs (MonoDynamicImage *assembly)
4123 MonoDynamicTable *table;
4125 guint32 type, i, idx, token;
4128 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4130 for (i = 0; i < table->rows; ++i) {
4131 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4133 type = values [MONO_CUSTOM_ATTR_TYPE];
4134 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4135 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4136 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4137 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4140 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4141 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4142 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4143 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4150 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4152 MonoDynamicTable *table;
4155 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4157 alloc_table (table, table->rows);
4158 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4159 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4160 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4161 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4162 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4167 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4169 MonoDynamicTable *table;
4173 char *b = blob_size;
4175 guint32 idx, offset;
4177 if (rsrc->filename) {
4178 name = mono_string_to_utf8 (rsrc->filename);
4179 sname = g_path_get_basename (name);
4181 table = &assembly->tables [MONO_TABLE_FILE];
4183 alloc_table (table, table->rows);
4184 values = table->values + table->next_idx * MONO_FILE_SIZE;
4185 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4186 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4189 mono_sha1_get_digest_from_file (name, hash);
4190 mono_metadata_encode_value (20, b, &b);
4191 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4192 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4194 idx = table->next_idx++;
4196 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4202 data = mono_array_addr (rsrc->data, char, 0);
4203 len = mono_array_length (rsrc->data);
4209 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4210 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4211 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4212 mono_image_add_stream_data (&assembly->resources, data, len);
4216 * The entry should be emitted into the MANIFESTRESOURCE table of
4217 * the main module, but that needs to reference the FILE table
4218 * which isn't emitted yet.
4225 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4229 set_version_from_string (MonoString *version, guint32 *values)
4231 gchar *ver, *p, *str;
4234 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4235 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4236 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4237 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4240 ver = str = mono_string_to_utf8 (version);
4241 for (i = 0; i < 4; ++i) {
4242 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4248 /* handle Revision and Build */
4258 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4262 char *b = blob_size;
4267 len = mono_array_length (pkey);
4268 mono_metadata_encode_value (len, b, &b);
4269 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4270 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4272 assembly->public_key = g_malloc (len);
4273 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4274 assembly->public_key_len = len;
4276 /* Special case: check for ECMA key (16 bytes) */
4277 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4278 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4279 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4280 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4281 /* minimum key size (in 2.0) is 384 bits */
4282 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4284 /* FIXME - verifier */
4285 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4286 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4288 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4294 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4296 MonoDynamicTable *table;
4297 MonoDynamicImage *assembly;
4298 MonoReflectionAssemblyBuilder *assemblyb;
4302 guint32 module_index;
4304 assemblyb = moduleb->assemblyb;
4305 assembly = moduleb->dynamic_image;
4306 domain = mono_object_domain (assemblyb);
4308 /* Emit ASSEMBLY table */
4309 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4310 alloc_table (table, 1);
4311 values = table->values + MONO_ASSEMBLY_SIZE;
4312 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4313 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4314 if (assemblyb->culture) {
4315 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4317 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4319 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4320 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4321 set_version_from_string (assemblyb->version, values);
4323 /* Emit FILE + EXPORTED_TYPE table */
4325 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4327 MonoReflectionModuleBuilder *file_module =
4328 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4329 if (file_module != moduleb) {
4330 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4332 if (file_module->types) {
4333 for (j = 0; j < file_module->num_types; ++j) {
4334 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4335 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4340 if (assemblyb->loaded_modules) {
4341 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4342 MonoReflectionModule *file_module =
4343 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4344 mono_image_fill_file_table (domain, file_module, assembly);
4346 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4349 if (assemblyb->type_forwarders)
4350 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4352 /* Emit MANIFESTRESOURCE table */
4354 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4356 MonoReflectionModuleBuilder *file_module =
4357 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4358 /* The table for the main module is emitted later */
4359 if (file_module != moduleb) {
4361 if (file_module->resources) {
4362 int len = mono_array_length (file_module->resources);
4363 for (j = 0; j < len; ++j) {
4364 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4365 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4372 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4375 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4376 * for the modulebuilder @moduleb.
4377 * At the end of the process, method and field tokens are fixed up and the
4378 * on-disk compressed metadata representation is created.
4381 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4383 MonoDynamicTable *table;
4384 MonoDynamicImage *assembly;
4385 MonoReflectionAssemblyBuilder *assemblyb;
4391 assemblyb = moduleb->assemblyb;
4392 assembly = moduleb->dynamic_image;
4393 domain = mono_object_domain (assemblyb);
4395 if (assembly->text_rva)
4398 assembly->text_rva = START_TEXT_RVA;
4400 if (moduleb->is_main) {
4401 mono_image_emit_manifest (moduleb);
4404 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4405 table->rows = 1; /* .<Module> */
4407 alloc_table (table, table->rows);
4409 * Set the first entry.
4411 values = table->values + table->columns;
4412 values [MONO_TYPEDEF_FLAGS] = 0;
4413 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4414 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4415 values [MONO_TYPEDEF_EXTENDS] = 0;
4416 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4417 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4420 * handle global methods
4421 * FIXME: test what to do when global methods are defined in multiple modules.
4423 if (moduleb->global_methods) {
4424 table = &assembly->tables [MONO_TABLE_METHOD];
4425 table->rows += mono_array_length (moduleb->global_methods);
4426 alloc_table (table, table->rows);
4427 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4428 mono_image_get_method_info (
4429 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4431 if (moduleb->global_fields) {
4432 table = &assembly->tables [MONO_TABLE_FIELD];
4433 table->rows += mono_array_length (moduleb->global_fields);
4434 alloc_table (table, table->rows);
4435 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4436 mono_image_get_field_info (
4437 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4440 table = &assembly->tables [MONO_TABLE_MODULE];
4441 alloc_table (table, 1);
4442 mono_image_fill_module_table (domain, moduleb, assembly);
4444 /* Collect all types into a list sorted by their table_idx */
4445 types = g_ptr_array_new ();
4448 for (i = 0; i < moduleb->num_types; ++i) {
4449 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4450 collect_types (types, type);
4453 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4454 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4455 table->rows += types->len;
4456 alloc_table (table, table->rows);
4459 * Emit type names + namespaces at one place inside the string heap,
4460 * so load_class_names () needs to touch fewer pages.
4462 for (i = 0; i < types->len; ++i) {
4463 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4464 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4466 for (i = 0; i < types->len; ++i) {
4467 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4468 string_heap_insert_mstring (&assembly->sheap, tb->name);
4471 for (i = 0; i < types->len; ++i) {
4472 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4473 mono_image_get_type_info (domain, type, assembly);
4477 * table->rows is already set above and in mono_image_fill_module_table.
4479 /* add all the custom attributes at the end, once all the indexes are stable */
4480 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4482 /* CAS assembly permissions */
4483 if (assemblyb->permissions_minimum)
4484 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4485 if (assemblyb->permissions_optional)
4486 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4487 if (assemblyb->permissions_refused)
4488 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4490 module_add_cattrs (assembly, moduleb);
4493 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4495 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4496 * the final tokens and don't need another fixup pass. */
4498 if (moduleb->global_methods) {
4499 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4500 MonoReflectionMethodBuilder *mb = mono_array_get (
4501 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4502 mono_image_add_methodimpl (assembly, mb);
4506 for (i = 0; i < types->len; ++i) {
4507 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4508 if (type->methods) {
4509 for (j = 0; j < type->num_methods; ++j) {
4510 MonoReflectionMethodBuilder *mb = mono_array_get (
4511 type->methods, MonoReflectionMethodBuilder*, j);
4513 mono_image_add_methodimpl (assembly, mb);
4518 g_ptr_array_free (types, TRUE);
4520 fixup_cattrs (assembly);
4523 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4526 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4528 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4531 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4535 guint32 import_lookup_table;
4539 guint32 import_address_table_rva;
4547 #ifndef DISABLE_REFLECTION_EMIT
4550 * mono_image_insert_string:
4551 * @module: module builder object
4554 * Insert @str into the user string stream of @module.
4557 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4559 MonoDynamicImage *assembly;
4564 MONO_ARCH_SAVE_REGS;
4566 if (!module->dynamic_image)
4567 mono_image_module_basic_init (module);
4569 assembly = module->dynamic_image;
4571 if (assembly->save) {
4572 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4573 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4574 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4576 char *swapped = g_malloc (2 * mono_string_length (str));
4577 const char *p = (const char*)mono_string_chars (str);
4579 swap_with_size (swapped, p, 2, mono_string_length (str));
4580 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4584 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4586 mono_image_add_stream_data (&assembly->us, "", 1);
4588 idx = assembly->us.index ++;
4591 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4593 return MONO_TOKEN_STRING | idx;
4597 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4602 klass = obj->vtable->klass;
4603 if (strcmp (klass->name, "MonoMethod") == 0) {
4604 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4605 MonoMethodSignature *sig, *old;
4606 guint32 sig_token, parent;
4609 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4611 nargs = mono_array_length (opt_param_types);
4612 old = mono_method_signature (method);
4613 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4615 sig->hasthis = old->hasthis;
4616 sig->explicit_this = old->explicit_this;
4617 sig->call_convention = old->call_convention;
4618 sig->generic_param_count = old->generic_param_count;
4619 sig->param_count = old->param_count + nargs;
4620 sig->sentinelpos = old->param_count;
4621 sig->ret = old->ret;
4623 for (i = 0; i < old->param_count; i++)
4624 sig->params [i] = old->params [i];
4626 for (i = 0; i < nargs; i++) {
4627 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4628 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4631 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4632 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4633 parent >>= MONO_TYPEDEFORREF_BITS;
4635 parent <<= MONO_MEMBERREF_PARENT_BITS;
4636 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4638 sig_token = method_encode_signature (assembly, sig);
4639 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4640 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4641 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4642 ReflectionMethodBuilder rmb;
4643 guint32 parent, sig;
4646 reflection_methodbuilder_from_method_builder (&rmb, mb);
4647 rmb.opt_types = opt_param_types;
4649 sig = method_builder_encode_signature (assembly, &rmb);
4651 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4652 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4654 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4655 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4657 name = mono_string_to_utf8 (rmb.name);
4658 token = mono_image_get_varargs_method_token (
4659 assembly, parent, name, sig);
4662 g_error ("requested method token for %s\n", klass->name);
4669 * mono_image_create_token:
4670 * @assembly: a dynamic assembly
4672 * @register_token: Whenever to register the token in the assembly->tokens hash.
4674 * Get a token to insert in the IL code stream for the given MemberInfo.
4675 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4676 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4680 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4681 gboolean create_methodspec, gboolean register_token)
4686 klass = obj->vtable->klass;
4688 /* Check for user defined reflection objects */
4689 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4690 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4691 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4693 if (strcmp (klass->name, "MethodBuilder") == 0) {
4694 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4695 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4697 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4698 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4700 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4701 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4702 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4703 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4704 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4706 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4707 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4709 token = mono_image_get_ctorbuilder_token (assembly, mb);
4710 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4711 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4712 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4713 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4714 if (tb->generic_params) {
4715 token = mono_image_get_generic_field_token (assembly, fb);
4717 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4719 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4720 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4721 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4722 } else if (strcmp (klass->name, "MonoType") == 0) {
4723 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4724 MonoClass *mc = mono_class_from_mono_type (type);
4725 token = mono_metadata_token_from_dor (
4726 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4727 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4728 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4729 token = mono_metadata_token_from_dor (
4730 mono_image_typedef_or_ref (assembly, type));
4731 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4732 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4733 token = mono_metadata_token_from_dor (
4734 mono_image_typedef_or_ref (assembly, type));
4735 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4736 strcmp (klass->name, "MonoMethod") == 0 ||
4737 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4738 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4739 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4740 if (m->method->is_inflated) {
4741 if (create_methodspec)
4742 token = mono_image_get_methodspec_token (assembly, m->method);
4744 token = mono_image_get_inflated_method_token (assembly, m->method);
4745 } else if ((m->method->klass->image == &assembly->image) &&
4746 !m->method->klass->generic_class) {
4747 static guint32 method_table_idx = 0xffffff;
4748 if (m->method->klass->wastypebuilder) {
4749 /* we use the same token as the one that was assigned
4750 * to the Methodbuilder.
4751 * FIXME: do the equivalent for Fields.
4753 token = m->method->token;
4756 * Each token should have a unique index, but the indexes are
4757 * assigned by managed code, so we don't know about them. An
4758 * easy solution is to count backwards...
4760 method_table_idx --;
4761 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4764 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4766 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4767 } else if (strcmp (klass->name, "MonoField") == 0) {
4768 MonoReflectionField *f = (MonoReflectionField *)obj;
4769 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4770 static guint32 field_table_idx = 0xffffff;
4772 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4774 token = mono_image_get_fieldref_token (assembly, f);
4776 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4777 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4778 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4779 token = mono_image_get_array_token (assembly, m);
4780 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4781 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4782 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4783 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4784 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4785 token = mono_metadata_token_from_dor (
4786 mono_image_typedef_or_ref (assembly, type));
4787 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4788 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4789 token = mono_image_get_field_on_inst_token (assembly, f);
4790 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4791 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4792 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4793 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4794 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4795 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4796 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4797 MonoReflectionType *type = (MonoReflectionType *)obj;
4798 token = mono_metadata_token_from_dor (
4799 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4801 g_error ("requested token for %s\n", klass->name);
4805 mono_image_register_token (assembly, token, obj);
4811 * mono_image_register_token:
4813 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4814 * the Module.ResolveXXXToken () methods to work.
4817 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4819 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4821 /* There could be multiple MethodInfo objects with the same token */
4822 //g_assert (prev == obj);
4824 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4828 static MonoDynamicImage*
4829 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4831 static const guchar entrycode [16] = {0xff, 0x25, 0};
4832 MonoDynamicImage *image;
4835 const char *version;
4837 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4838 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4840 version = mono_get_runtime_info ()->runtime_version;
4843 image = GC_MALLOC (sizeof (MonoDynamicImage));
4845 image = g_new0 (MonoDynamicImage, 1);
4848 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4850 /*g_print ("created image %p\n", image);*/
4851 /* keep in sync with image.c */
4852 image->image.name = assembly_name;
4853 image->image.assembly_name = image->image.name; /* they may be different */
4854 image->image.module_name = module_name;
4855 image->image.version = g_strdup (version);
4856 image->image.md_version_major = 1;
4857 image->image.md_version_minor = 1;
4858 image->image.dynamic = TRUE;
4860 image->image.references = g_new0 (MonoAssembly*, 1);
4861 image->image.references [0] = NULL;
4863 mono_image_init (&image->image);
4865 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4866 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4867 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4868 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4869 image->handleref = g_hash_table_new (NULL, NULL);
4870 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4871 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4872 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4873 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4874 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4875 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4876 image->gen_params = g_ptr_array_new ();
4878 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4879 string_heap_init (&image->sheap);
4880 mono_image_add_stream_data (&image->us, "", 1);
4881 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4882 /* import tables... */
4883 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4884 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4885 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4886 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4887 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4888 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4889 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4890 stream_data_align (&image->code);
4892 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4894 for (i=0; i < MONO_TABLE_NUM; ++i) {
4895 image->tables [i].next_idx = 1;
4896 image->tables [i].columns = table_sizes [i];
4899 image->image.assembly = (MonoAssembly*)assembly;
4900 image->run = assembly->run;
4901 image->save = assembly->save;
4902 image->pe_kind = 0x1; /* ILOnly */
4903 image->machine = 0x14c; /* I386 */
4905 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4912 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4918 mono_dynamic_image_free (MonoDynamicImage *image)
4920 MonoDynamicImage *di = image;
4925 mono_g_hash_table_destroy (di->methodspec);
4927 g_hash_table_destroy (di->typespec);
4929 g_hash_table_destroy (di->typeref);
4931 g_hash_table_destroy (di->handleref);
4933 mono_g_hash_table_destroy (di->tokens);
4934 if (di->generic_def_objects)
4935 mono_g_hash_table_destroy (di->generic_def_objects);
4936 if (di->blob_cache) {
4937 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4938 g_hash_table_destroy (di->blob_cache);
4940 if (di->standalonesig_cache)
4941 g_hash_table_destroy (di->standalonesig_cache);
4942 for (list = di->array_methods; list; list = list->next) {
4943 ArrayMethod *am = (ArrayMethod *)list->data;
4948 g_list_free (di->array_methods);
4949 if (di->gen_params) {
4950 for (i = 0; i < di->gen_params->len; i++) {
4951 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4952 if (entry->gparam->type.type) {
4953 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4954 g_free ((char*)mono_generic_param_info (param)->name);
4957 mono_gc_deregister_root ((char*) &entry->gparam);
4960 g_ptr_array_free (di->gen_params, TRUE);
4962 if (di->token_fixups)
4963 mono_g_hash_table_destroy (di->token_fixups);
4964 if (di->method_to_table_idx)
4965 g_hash_table_destroy (di->method_to_table_idx);
4966 if (di->field_to_table_idx)
4967 g_hash_table_destroy (di->field_to_table_idx);
4968 if (di->method_aux_hash)
4969 g_hash_table_destroy (di->method_aux_hash);
4970 g_free (di->strong_name);
4971 g_free (di->win32_res);
4973 g_free (di->public_key);
4975 /*g_print ("string heap destroy for image %p\n", di);*/
4976 mono_dynamic_stream_reset (&di->sheap);
4977 mono_dynamic_stream_reset (&di->code);
4978 mono_dynamic_stream_reset (&di->resources);
4979 mono_dynamic_stream_reset (&di->us);
4980 mono_dynamic_stream_reset (&di->blob);
4981 mono_dynamic_stream_reset (&di->tstream);
4982 mono_dynamic_stream_reset (&di->guid);
4983 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4984 g_free (di->tables [i].values);
4988 #ifndef DISABLE_REFLECTION_EMIT
4991 * mono_image_basic_init:
4992 * @assembly: an assembly builder object
4994 * Create the MonoImage that represents the assembly builder and setup some
4995 * of the helper hash table and the basic metadata streams.
4998 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5000 MonoDynamicAssembly *assembly;
5001 MonoDynamicImage *image;
5002 MonoDomain *domain = mono_object_domain (assemblyb);
5004 MONO_ARCH_SAVE_REGS;
5006 if (assemblyb->dynamic_assembly)
5010 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5012 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5015 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5017 assembly->assembly.ref_count = 1;
5018 assembly->assembly.dynamic = TRUE;
5019 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5020 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5021 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5022 if (assemblyb->culture)
5023 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5025 assembly->assembly.aname.culture = g_strdup ("");
5027 if (assemblyb->version) {
5028 char *vstr = mono_string_to_utf8 (assemblyb->version);
5029 char **version = g_strsplit (vstr, ".", 4);
5030 char **parts = version;
5031 assembly->assembly.aname.major = atoi (*parts++);
5032 assembly->assembly.aname.minor = atoi (*parts++);
5033 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5034 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5036 g_strfreev (version);
5039 assembly->assembly.aname.major = 0;
5040 assembly->assembly.aname.minor = 0;
5041 assembly->assembly.aname.build = 0;
5042 assembly->assembly.aname.revision = 0;
5045 assembly->run = assemblyb->access != 2;
5046 assembly->save = assemblyb->access != 1;
5048 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5049 image->initial_image = TRUE;
5050 assembly->assembly.aname.name = image->image.name;
5051 assembly->assembly.image = &image->image;
5052 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5053 /* -1 to correct for the trailing NULL byte */
5054 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5055 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5057 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5060 mono_domain_assemblies_lock (domain);
5061 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5062 mono_domain_assemblies_unlock (domain);
5064 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5066 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5068 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5071 #endif /* !DISABLE_REFLECTION_EMIT */
5073 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5076 calc_section_size (MonoDynamicImage *assembly)
5080 /* alignment constraints */
5081 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5082 g_assert ((assembly->code.index % 4) == 0);
5083 assembly->meta_size += 3;
5084 assembly->meta_size &= ~3;
5085 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5086 g_assert ((assembly->resources.index % 4) == 0);
5088 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5089 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5092 if (assembly->win32_res) {
5093 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5095 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5096 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5100 assembly->sections [MONO_SECTION_RELOC].size = 12;
5101 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5111 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5115 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5117 ResTreeNode *t1 = (ResTreeNode*)a;
5118 ResTreeNode *t2 = (ResTreeNode*)b;
5120 return t1->id - t2->id;
5124 * resource_tree_create:
5126 * Organize the resources into a resource tree.
5128 static ResTreeNode *
5129 resource_tree_create (MonoArray *win32_resources)
5131 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5135 tree = g_new0 (ResTreeNode, 1);
5137 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5138 MonoReflectionWin32Resource *win32_res =
5139 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5143 /* FIXME: BUG: this stores managed references in unmanaged memory */
5144 lang_node = g_new0 (ResTreeNode, 1);
5145 lang_node->id = win32_res->lang_id;
5146 lang_node->win32_res = win32_res;
5148 /* Create type node if neccesary */
5150 for (l = tree->children; l; l = l->next)
5151 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5152 type_node = (ResTreeNode*)l->data;
5157 type_node = g_new0 (ResTreeNode, 1);
5158 type_node->id = win32_res->res_type;
5161 * The resource types have to be sorted otherwise
5162 * Windows Explorer can't display the version information.
5164 tree->children = g_slist_insert_sorted (tree->children,
5165 type_node, resource_tree_compare_by_id);
5168 /* Create res node if neccesary */
5170 for (l = type_node->children; l; l = l->next)
5171 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5172 res_node = (ResTreeNode*)l->data;
5177 res_node = g_new0 (ResTreeNode, 1);
5178 res_node->id = win32_res->res_id;
5179 type_node->children = g_slist_append (type_node->children, res_node);
5182 res_node->children = g_slist_append (res_node->children, lang_node);
5189 * resource_tree_encode:
5191 * Encode the resource tree into the format used in the PE file.
5194 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5197 MonoPEResourceDir dir;
5198 MonoPEResourceDirEntry dir_entry;
5199 MonoPEResourceDataEntry data_entry;
5201 guint32 res_id_entries;
5204 * For the format of the resource directory, see the article
5205 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5209 memset (&dir, 0, sizeof (dir));
5210 memset (&dir_entry, 0, sizeof (dir_entry));
5211 memset (&data_entry, 0, sizeof (data_entry));
5213 g_assert (sizeof (dir) == 16);
5214 g_assert (sizeof (dir_entry) == 8);
5215 g_assert (sizeof (data_entry) == 16);
5217 node->offset = p - begin;
5219 /* IMAGE_RESOURCE_DIRECTORY */
5220 res_id_entries = g_slist_length (node->children);
5221 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5223 memcpy (p, &dir, sizeof (dir));
5226 /* Reserve space for entries */
5228 p += sizeof (dir_entry) * res_id_entries;
5230 /* Write children */
5231 for (l = node->children; l; l = l->next) {
5232 ResTreeNode *child = (ResTreeNode*)l->data;
5234 if (child->win32_res) {
5237 child->offset = p - begin;
5239 /* IMAGE_RESOURCE_DATA_ENTRY */
5240 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5241 size = mono_array_length (child->win32_res->res_data);
5242 data_entry.rde_size = GUINT32_TO_LE (size);
5244 memcpy (p, &data_entry, sizeof (data_entry));
5245 p += sizeof (data_entry);
5247 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5250 resource_tree_encode (child, begin, p, &p);
5254 /* IMAGE_RESOURCE_ENTRY */
5255 for (l = node->children; l; l = l->next) {
5256 ResTreeNode *child = (ResTreeNode*)l->data;
5258 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5259 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5261 memcpy (entries, &dir_entry, sizeof (dir_entry));
5262 entries += sizeof (dir_entry);
5269 resource_tree_free (ResTreeNode * node)
5272 for (list = node->children; list; list = list->next)
5273 resource_tree_free ((ResTreeNode*)list->data);
5274 g_slist_free(node->children);
5279 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5284 MonoReflectionWin32Resource *win32_res;
5287 if (!assemblyb->win32_resources)
5291 * Resources are stored in a three level tree inside the PE file.
5292 * - level one contains a node for each type of resource
5293 * - level two contains a node for each resource
5294 * - level three contains a node for each instance of a resource for a
5295 * specific language.
5298 tree = resource_tree_create (assemblyb->win32_resources);
5300 /* Estimate the size of the encoded tree */
5302 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5303 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5304 size += mono_array_length (win32_res->res_data);
5306 /* Directory structure */
5307 size += mono_array_length (assemblyb->win32_resources) * 256;
5308 p = buf = g_malloc (size);
5310 resource_tree_encode (tree, p, p, &p);
5312 g_assert (p - buf <= size);
5314 assembly->win32_res = g_malloc (p - buf);
5315 assembly->win32_res_size = p - buf;
5316 memcpy (assembly->win32_res, buf, p - buf);
5319 resource_tree_free (tree);
5323 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5325 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5328 p += sizeof (MonoPEResourceDir);
5329 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5330 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5331 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5332 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5333 fixup_resource_directory (res_section, child, rva);
5335 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5336 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5339 p += sizeof (MonoPEResourceDirEntry);
5344 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5347 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5348 g_error ("WriteFile returned %d\n", GetLastError ());
5352 * mono_image_create_pefile:
5353 * @mb: a module builder object
5355 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5356 * assembly->pefile where it can be easily retrieved later in chunks.
5359 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5361 MonoMSDOSHeader *msdos;
5362 MonoDotNetHeader *header;
5363 MonoSectionTable *section;
5364 MonoCLIHeader *cli_header;
5365 guint32 size, image_size, virtual_base, text_offset;
5366 guint32 header_start, section_start, file_offset, virtual_offset;
5367 MonoDynamicImage *assembly;
5368 MonoReflectionAssemblyBuilder *assemblyb;
5369 MonoDynamicStream pefile_stream = {0};
5370 MonoDynamicStream *pefile = &pefile_stream;
5372 guint32 *rva, value;
5374 static const unsigned char msheader[] = {
5375 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5376 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5379 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5380 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5381 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5382 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5385 assemblyb = mb->assemblyb;
5387 mono_image_basic_init (assemblyb);
5388 assembly = mb->dynamic_image;
5390 assembly->pe_kind = assemblyb->pe_kind;
5391 assembly->machine = assemblyb->machine;
5392 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5393 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5395 mono_image_build_metadata (mb);
5397 if (mb->is_main && assemblyb->resources) {
5398 int len = mono_array_length (assemblyb->resources);
5399 for (i = 0; i < len; ++i)
5400 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5403 if (mb->resources) {
5404 int len = mono_array_length (mb->resources);
5405 for (i = 0; i < len; ++i)
5406 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5409 build_compressed_metadata (assembly);
5412 assembly_add_win32_resources (assembly, assemblyb);
5414 nsections = calc_section_size (assembly);
5416 /* The DOS header and stub */
5417 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5418 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5420 /* the dotnet header */
5421 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5423 /* the section tables */
5424 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5426 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5427 virtual_offset = VIRT_ALIGN;
5430 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5431 if (!assembly->sections [i].size)
5434 file_offset += FILE_ALIGN - 1;
5435 file_offset &= ~(FILE_ALIGN - 1);
5436 virtual_offset += VIRT_ALIGN - 1;
5437 virtual_offset &= ~(VIRT_ALIGN - 1);
5439 assembly->sections [i].offset = file_offset;
5440 assembly->sections [i].rva = virtual_offset;
5442 file_offset += assembly->sections [i].size;
5443 virtual_offset += assembly->sections [i].size;
5444 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5447 file_offset += FILE_ALIGN - 1;
5448 file_offset &= ~(FILE_ALIGN - 1);
5450 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5452 /* back-patch info */
5453 msdos = (MonoMSDOSHeader*)pefile->data;
5454 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5456 header = (MonoDotNetHeader*)(pefile->data + header_start);
5457 header->pesig [0] = 'P';
5458 header->pesig [1] = 'E';
5460 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5461 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5462 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5463 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5464 if (assemblyb->pekind == 1) {
5466 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5469 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5472 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5474 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5475 header->pe.pe_major = 6;
5476 header->pe.pe_minor = 0;
5477 size = assembly->sections [MONO_SECTION_TEXT].size;
5478 size += FILE_ALIGN - 1;
5479 size &= ~(FILE_ALIGN - 1);
5480 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5481 size = assembly->sections [MONO_SECTION_RSRC].size;
5482 size += FILE_ALIGN - 1;
5483 size &= ~(FILE_ALIGN - 1);
5484 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5485 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5486 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5487 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5488 /* pe_rva_entry_point always at the beginning of the text section */
5489 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5491 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5492 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5493 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5494 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5495 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5496 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5497 size = section_start;
5498 size += FILE_ALIGN - 1;
5499 size &= ~(FILE_ALIGN - 1);
5500 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5502 size += VIRT_ALIGN - 1;
5503 size &= ~(VIRT_ALIGN - 1);
5504 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5507 // Translate the PEFileKind value to the value expected by the Windows loader
5513 // PEFileKinds.Dll == 1
5514 // PEFileKinds.ConsoleApplication == 2
5515 // PEFileKinds.WindowApplication == 3
5518 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5519 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5521 if (assemblyb->pekind == 3)
5526 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5528 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5529 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5530 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5531 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5532 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5533 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5535 /* fill data directory entries */
5537 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5538 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5540 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5541 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5543 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5544 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5545 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5546 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5547 /* patch entrypoint name */
5548 if (assemblyb->pekind == 1)
5549 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5551 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5552 /* patch imported function RVA name */
5553 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5554 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5556 /* the import table */
5557 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5558 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5559 /* patch imported dll RVA name and other entries in the dir */
5560 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5561 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5562 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5563 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5564 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5565 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5567 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5568 value = (assembly->text_rva + assembly->imp_names_offset);
5569 *p++ = (value) & 0xff;
5570 *p++ = (value >> 8) & (0xff);
5571 *p++ = (value >> 16) & (0xff);
5572 *p++ = (value >> 24) & (0xff);
5574 /* the CLI header info */
5575 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5576 cli_header->ch_size = GUINT32_FROM_LE (72);
5577 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5578 if (mono_framework_version () > 1)
5579 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5581 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5582 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5583 if (assemblyb->entry_point) {
5584 guint32 table_idx = 0;
5585 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5586 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5587 table_idx = methodb->table_idx;
5589 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5591 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5593 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5595 /* The embedded managed resources */
5596 text_offset = assembly->text_rva + assembly->code.index;
5597 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5598 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5599 text_offset += assembly->resources.index;
5600 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5601 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5602 text_offset += assembly->meta_size;
5603 if (assembly->strong_name_size) {
5604 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5605 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5606 text_offset += assembly->strong_name_size;
5609 /* write the section tables and section content */
5610 section = (MonoSectionTable*)(pefile->data + section_start);
5611 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5612 static const char section_names [][7] = {
5613 ".text", ".rsrc", ".reloc"
5615 if (!assembly->sections [i].size)
5617 strcpy (section->st_name, section_names [i]);
5618 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5619 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5620 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5621 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5622 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5623 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5624 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5628 checked_write_file (file, pefile->data, pefile->index);
5630 mono_dynamic_stream_reset (pefile);
5632 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5633 if (!assembly->sections [i].size)
5636 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5637 g_error ("SetFilePointer returned %d\n", GetLastError ());
5640 case MONO_SECTION_TEXT:
5641 /* patch entry point */
5642 p = (guchar*)(assembly->code.data + 2);
5643 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5644 *p++ = (value) & 0xff;
5645 *p++ = (value >> 8) & 0xff;
5646 *p++ = (value >> 16) & 0xff;
5647 *p++ = (value >> 24) & 0xff;
5649 checked_write_file (file, assembly->code.data, assembly->code.index);
5650 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5651 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5652 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5655 g_free (assembly->image.raw_metadata);
5657 case MONO_SECTION_RELOC: {
5661 guint16 type_and_offset;
5665 g_assert (sizeof (reloc) == 12);
5667 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5668 reloc.block_size = GUINT32_FROM_LE (12);
5671 * the entrypoint is always at the start of the text section
5672 * 3 is IMAGE_REL_BASED_HIGHLOW
5673 * 2 is patch_size_rva - text_rva
5675 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5678 checked_write_file (file, &reloc, sizeof (reloc));
5682 case MONO_SECTION_RSRC:
5683 if (assembly->win32_res) {
5685 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5686 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5687 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5691 g_assert_not_reached ();
5695 /* check that the file is properly padded */
5696 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5697 g_error ("SetFilePointer returned %d\n", GetLastError ());
5698 if (! SetEndOfFile (file))
5699 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5701 mono_dynamic_stream_reset (&assembly->code);
5702 mono_dynamic_stream_reset (&assembly->us);
5703 mono_dynamic_stream_reset (&assembly->blob);
5704 mono_dynamic_stream_reset (&assembly->guid);
5705 mono_dynamic_stream_reset (&assembly->sheap);
5707 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5708 g_hash_table_destroy (assembly->blob_cache);
5709 assembly->blob_cache = NULL;
5712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5715 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5717 g_assert_not_reached ();
5720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5722 #ifndef DISABLE_REFLECTION_EMIT
5724 MonoReflectionModule *
5725 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5729 MonoImageOpenStatus status;
5730 MonoDynamicAssembly *assembly;
5731 guint32 module_count;
5732 MonoImage **new_modules;
5733 gboolean *new_modules_loaded;
5735 name = mono_string_to_utf8 (fileName);
5737 image = mono_image_open (name, &status);
5740 if (status == MONO_IMAGE_ERROR_ERRNO)
5741 exc = mono_get_exception_file_not_found (fileName);
5743 exc = mono_get_exception_bad_image_format (name);
5745 mono_raise_exception (exc);
5750 assembly = ab->dynamic_assembly;
5751 image->assembly = (MonoAssembly*)assembly;
5753 module_count = image->assembly->image->module_count;
5754 new_modules = g_new0 (MonoImage *, module_count + 1);
5755 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5757 if (image->assembly->image->modules)
5758 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5759 if (image->assembly->image->modules_loaded)
5760 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5761 new_modules [module_count] = image;
5762 new_modules_loaded [module_count] = TRUE;
5763 mono_image_addref (image);
5765 g_free (image->assembly->image->modules);
5766 image->assembly->image->modules = new_modules;
5767 image->assembly->image->modules_loaded = new_modules_loaded;
5768 image->assembly->image->module_count ++;
5770 mono_assembly_load_references (image, &status);
5772 mono_image_close (image);
5773 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5776 return mono_module_get_object (mono_domain_get (), image);
5779 #endif /* DISABLE_REFLECTION_EMIT */
5782 * We need to return always the same object for MethodInfo, FieldInfo etc..
5783 * but we need to consider the reflected type.
5784 * type uses a different hash, since it uses custom hash/equal functions.
5789 MonoClass *refclass;
5793 reflected_equal (gconstpointer a, gconstpointer b) {
5794 const ReflectedEntry *ea = a;
5795 const ReflectedEntry *eb = b;
5797 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5801 reflected_hash (gconstpointer a) {
5802 const ReflectedEntry *ea = a;
5803 return mono_aligned_addr_hash (ea->item);
5806 #define CHECK_OBJECT(t,p,k) \
5812 mono_domain_lock (domain); \
5813 if (!domain->refobject_hash) \
5814 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5815 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5816 mono_domain_unlock (domain); \
5819 mono_domain_unlock (domain); \
5822 #ifdef HAVE_BOEHM_GC
5823 /* ReflectedEntry doesn't need to be GC tracked */
5824 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5825 #define FREE_REFENTRY(entry) g_free ((entry))
5826 #define REFENTRY_REQUIRES_CLEANUP
5828 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5830 #define FREE_REFENTRY(entry)
5833 #define CACHE_OBJECT(t,p,o,k) \
5836 ReflectedEntry pe; \
5838 pe.refclass = (k); \
5839 mono_domain_lock (domain); \
5840 if (!domain->refobject_hash) \
5841 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5842 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5844 ReflectedEntry *e = ALLOC_REFENTRY; \
5846 e->refclass = (k); \
5847 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5850 mono_domain_unlock (domain); \
5855 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5857 mono_domain_lock (domain);
5858 if (domain->refobject_hash) {
5860 gpointer orig_pe, orig_value;
5863 pe.refclass = klass;
5864 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5865 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5866 FREE_REFENTRY (orig_pe);
5869 mono_domain_unlock (domain);
5872 #ifdef REFENTRY_REQUIRES_CLEANUP
5874 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5876 FREE_REFENTRY (key);
5881 mono_reflection_cleanup_domain (MonoDomain *domain)
5883 if (domain->refobject_hash) {
5884 /*let's avoid scanning the whole hashtable if not needed*/
5885 #ifdef REFENTRY_REQUIRES_CLEANUP
5886 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5888 mono_g_hash_table_destroy (domain->refobject_hash);
5889 domain->refobject_hash = NULL;
5893 #ifndef DISABLE_REFLECTION_EMIT
5895 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5897 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5901 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5903 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5907 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5909 MonoDynamicImage *image = moduleb->dynamic_image;
5910 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5913 MonoImage **new_modules;
5916 * FIXME: we already created an image in mono_image_basic_init (), but
5917 * we don't know which module it belongs to, since that is only
5918 * determined at assembly save time.
5920 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5921 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5923 moduleb->module.image = &image->image;
5924 moduleb->dynamic_image = image;
5925 register_module (mono_object_domain (moduleb), moduleb, image);
5927 /* register the module with the assembly */
5928 ass = ab->dynamic_assembly->assembly.image;
5929 module_count = ass->module_count;
5930 new_modules = g_new0 (MonoImage *, module_count + 1);
5933 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5934 new_modules [module_count] = &image->image;
5935 mono_image_addref (&image->image);
5937 g_free (ass->modules);
5938 ass->modules = new_modules;
5939 ass->module_count ++;
5944 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
5946 MonoDynamicImage *image = moduleb->dynamic_image;
5948 g_assert (type->type);
5949 image->wrappers_type = mono_class_from_mono_type (type->type);
5955 * mono_assembly_get_object:
5956 * @domain: an app domain
5957 * @assembly: an assembly
5959 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5961 MonoReflectionAssembly*
5962 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5964 static MonoClass *System_Reflection_Assembly;
5965 MonoReflectionAssembly *res;
5967 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5968 if (!System_Reflection_Assembly)
5969 System_Reflection_Assembly = mono_class_from_name (
5970 mono_defaults.corlib, "System.Reflection", "Assembly");
5971 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5972 res->assembly = assembly;
5974 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5979 MonoReflectionModule*
5980 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5982 static MonoClass *System_Reflection_Module;
5983 MonoReflectionModule *res;
5986 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5987 if (!System_Reflection_Module)
5988 System_Reflection_Module = mono_class_from_name (
5989 mono_defaults.corlib, "System.Reflection", "Module");
5990 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5993 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5995 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5996 basename = g_path_get_basename (image->name);
5997 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5998 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6002 if (image->assembly->image == image) {
6003 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6007 if (image->assembly->image->modules) {
6008 for (i = 0; i < image->assembly->image->module_count; i++) {
6009 if (image->assembly->image->modules [i] == image)
6010 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6012 g_assert (res->token);
6016 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6019 MonoReflectionModule*
6020 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6022 static MonoClass *System_Reflection_Module;
6023 MonoReflectionModule *res;
6024 MonoTableInfo *table;
6025 guint32 cols [MONO_FILE_SIZE];
6027 guint32 i, name_idx;
6030 if (!System_Reflection_Module)
6031 System_Reflection_Module = mono_class_from_name (
6032 mono_defaults.corlib, "System.Reflection", "Module");
6033 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6035 table = &image->tables [MONO_TABLE_FILE];
6036 g_assert (table_index < table->rows);
6037 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6040 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6041 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6043 /* Check whenever the row has a corresponding row in the moduleref table */
6044 table = &image->tables [MONO_TABLE_MODULEREF];
6045 for (i = 0; i < table->rows; ++i) {
6046 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6047 val = mono_metadata_string_heap (image, name_idx);
6048 if (strcmp (val, name) == 0)
6049 res->image = image->modules [i];
6052 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6053 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6054 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6055 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6056 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6062 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6064 if ((t1->type != t2->type) ||
6065 (t1->byref != t2->byref))
6069 case MONO_TYPE_VOID:
6070 case MONO_TYPE_BOOLEAN:
6071 case MONO_TYPE_CHAR:
6082 case MONO_TYPE_STRING:
6085 case MONO_TYPE_OBJECT:
6086 case MONO_TYPE_TYPEDBYREF:
6088 case MONO_TYPE_VALUETYPE:
6089 case MONO_TYPE_CLASS:
6090 case MONO_TYPE_SZARRAY:
6091 return t1->data.klass == t2->data.klass;
6093 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6094 case MONO_TYPE_ARRAY:
6095 if (t1->data.array->rank != t2->data.array->rank)
6097 return t1->data.array->eklass == t2->data.array->eklass;
6098 case MONO_TYPE_GENERICINST: {
6100 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6101 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6102 if (i1->type_argc != i2->type_argc)
6104 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6105 &t2->data.generic_class->container_class->byval_arg))
6107 /* FIXME: we should probably just compare the instance pointers directly. */
6108 for (i = 0; i < i1->type_argc; ++i) {
6109 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6115 case MONO_TYPE_MVAR:
6116 return t1->data.generic_param == t2->data.generic_param;
6118 g_error ("implement type compare for %0x!", t1->type);
6126 mymono_metadata_type_hash (MonoType *t1)
6132 hash |= t1->byref << 6; /* do not collide with t1->type values */
6134 case MONO_TYPE_VALUETYPE:
6135 case MONO_TYPE_CLASS:
6136 case MONO_TYPE_SZARRAY:
6137 /* check if the distribution is good enough */
6138 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6140 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6141 case MONO_TYPE_GENERICINST: {
6143 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6144 hash += g_str_hash (t1->data.generic_class->container_class->name);
6146 for (i = 0; i < inst->type_argc; ++i) {
6147 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6156 static MonoReflectionGenericClass*
6157 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6159 static MonoClass *System_Reflection_MonoGenericClass;
6160 MonoReflectionGenericClass *res;
6161 MonoClass *klass, *gklass;
6162 MonoGenericInst *ginst;
6163 MonoArray *type_args;
6166 if (!System_Reflection_MonoGenericClass) {
6167 System_Reflection_MonoGenericClass = mono_class_from_name (
6168 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6169 g_assert (System_Reflection_MonoGenericClass);
6172 klass = mono_class_from_mono_type (geninst);
6173 gklass = klass->generic_class->container_class;
6175 mono_class_init (klass);
6178 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6180 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6183 res->type.type = geninst;
6184 g_assert (gklass->reflection_info);
6185 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6186 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6188 ginst = klass->generic_class->context.class_inst;
6189 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6190 for (i = 0; i < ginst->type_argc; ++i)
6191 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6192 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6198 verify_safe_for_managed_space (MonoType *type)
6200 switch (type->type) {
6202 case MONO_TYPE_ARRAY:
6203 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6205 return verify_safe_for_managed_space (type->data.type);
6206 case MONO_TYPE_SZARRAY:
6207 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6208 case MONO_TYPE_GENERICINST: {
6209 MonoGenericInst *inst = type->data.generic_class->inst;
6213 for (i = 0; i < inst->type_argc; ++i)
6214 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6220 case MONO_TYPE_MVAR:
6227 * mono_type_get_object:
6228 * @domain: an app domain
6231 * Return an System.MonoType object representing the type @type.
6234 mono_type_get_object (MonoDomain *domain, MonoType *type)
6236 MonoReflectionType *res;
6237 MonoClass *klass = mono_class_from_mono_type (type);
6239 /*we must avoid using @type as it might have come
6240 * from a mono_metadata_type_dup and the caller
6241 * expects that is can be freed.
6242 * Using the right type from
6244 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6246 /* void is very common */
6247 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6248 return (MonoReflectionType*)domain->typeof_void;
6251 * If the vtable of the given class was already created, we can use
6252 * the MonoType from there and avoid all locking and hash table lookups.
6254 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6255 * that the resulting object is different.
6257 if (type == &klass->byval_arg && !klass->image->dynamic) {
6258 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6259 if (vtable && vtable->type)
6260 return vtable->type;
6263 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6264 mono_domain_lock (domain);
6265 if (!domain->type_hash)
6266 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6267 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6268 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6269 mono_domain_unlock (domain);
6270 mono_loader_unlock ();
6273 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6274 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6275 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6276 mono_g_hash_table_insert (domain->type_hash, type, res);
6277 mono_domain_unlock (domain);
6278 mono_loader_unlock ();
6282 if (!verify_safe_for_managed_space (type)) {
6283 mono_domain_unlock (domain);
6284 mono_loader_unlock ();
6285 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6288 if (klass->reflection_info && !klass->wastypebuilder) {
6289 /* g_assert_not_reached (); */
6290 /* should this be considered an error condition? */
6292 mono_domain_unlock (domain);
6293 mono_loader_unlock ();
6294 return klass->reflection_info;
6297 // FIXME: Get rid of this, do it in the icalls for Type
6298 mono_class_init (klass);
6300 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6302 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6305 mono_g_hash_table_insert (domain->type_hash, type, res);
6307 if (type->type == MONO_TYPE_VOID)
6308 domain->typeof_void = (MonoObject*)res;
6310 mono_domain_unlock (domain);
6311 mono_loader_unlock ();
6316 * mono_method_get_object:
6317 * @domain: an app domain
6319 * @refclass: the reflected type (can be NULL)
6321 * Return an System.Reflection.MonoMethod object representing the method @method.
6323 MonoReflectionMethod*
6324 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6327 * We use the same C representation for methods and constructors, but the type
6328 * name in C# is different.
6330 static MonoClass *System_Reflection_MonoMethod = NULL;
6331 static MonoClass *System_Reflection_MonoCMethod = NULL;
6332 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6333 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6335 MonoReflectionMethod *ret;
6337 if (method->is_inflated) {
6338 MonoReflectionGenericMethod *gret;
6340 refclass = method->klass;
6341 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6342 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6343 if (!System_Reflection_MonoGenericCMethod)
6344 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6345 klass = System_Reflection_MonoGenericCMethod;
6347 if (!System_Reflection_MonoGenericMethod)
6348 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6349 klass = System_Reflection_MonoGenericMethod;
6351 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6352 gret->method.method = method;
6353 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6354 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6355 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6359 refclass = method->klass;
6361 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6362 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6363 if (!System_Reflection_MonoCMethod)
6364 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6365 klass = System_Reflection_MonoCMethod;
6368 if (!System_Reflection_MonoMethod)
6369 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6370 klass = System_Reflection_MonoMethod;
6372 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6373 ret->method = method;
6374 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6375 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6379 * mono_method_clear_object:
6381 * Clear the cached reflection objects for the dynamic method METHOD.
6384 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6387 g_assert (method->dynamic);
6389 klass = method->klass;
6391 clear_cached_object (domain, method, klass);
6392 klass = klass->parent;
6394 /* Added by mono_param_get_objects () */
6395 clear_cached_object (domain, &(method->signature), NULL);
6396 klass = method->klass;
6398 clear_cached_object (domain, &(method->signature), klass);
6399 klass = klass->parent;
6404 * mono_field_get_object:
6405 * @domain: an app domain
6409 * Return an System.Reflection.MonoField object representing the field @field
6412 MonoReflectionField*
6413 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6415 MonoReflectionField *res;
6416 static MonoClass *monofield_klass;
6418 CHECK_OBJECT (MonoReflectionField *, field, klass);
6419 if (!monofield_klass)
6420 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6421 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6424 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6425 if (is_field_on_inst (field))
6426 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6428 res->attrs = field->type->attrs;
6429 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6430 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6434 * mono_property_get_object:
6435 * @domain: an app domain
6437 * @property: a property
6439 * Return an System.Reflection.MonoProperty object representing the property @property
6442 MonoReflectionProperty*
6443 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6445 MonoReflectionProperty *res;
6446 static MonoClass *monoproperty_klass;
6448 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6449 if (!monoproperty_klass)
6450 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6451 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6453 res->property = property;
6454 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6458 * mono_event_get_object:
6459 * @domain: an app domain
6463 * Return an System.Reflection.MonoEvent object representing the event @event
6466 MonoReflectionEvent*
6467 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6469 MonoReflectionEvent *res;
6470 MonoReflectionMonoEvent *mono_event;
6471 static MonoClass *monoevent_klass;
6473 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6474 if (!monoevent_klass)
6475 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6476 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6477 mono_event->klass = klass;
6478 mono_event->event = event;
6479 res = (MonoReflectionEvent*)mono_event;
6480 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6484 * mono_get_reflection_missing_object:
6485 * @domain: Domain where the object lives
6487 * Returns the System.Reflection.Missing.Value singleton object
6488 * (of type System.Reflection.Missing).
6490 * Used as the value for ParameterInfo.DefaultValue when Optional
6494 mono_get_reflection_missing_object (MonoDomain *domain)
6497 static MonoClassField *missing_value_field = NULL;
6499 if (!missing_value_field) {
6500 MonoClass *missing_klass;
6501 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6502 mono_class_init (missing_klass);
6503 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6504 g_assert (missing_value_field);
6506 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6512 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6515 *dbnull = mono_get_dbnull_object (domain);
6520 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6522 if (!*reflection_missing)
6523 *reflection_missing = mono_get_reflection_missing_object (domain);
6524 return *reflection_missing;
6528 * mono_param_get_objects:
6529 * @domain: an app domain
6532 * Return an System.Reflection.ParameterInfo array object representing the parameters
6533 * in the method @method.
6536 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6538 static MonoClass *System_Reflection_ParameterInfo;
6539 static MonoClass *System_Reflection_ParameterInfo_array;
6540 MonoArray *res = NULL;
6541 MonoReflectionMethod *member = NULL;
6542 MonoReflectionParameter *param = NULL;
6543 char **names, **blobs = NULL;
6544 guint32 *types = NULL;
6545 MonoType *type = NULL;
6546 MonoObject *dbnull = NULL;
6547 MonoObject *missing = NULL;
6548 MonoMarshalSpec **mspecs;
6549 MonoMethodSignature *sig;
6550 MonoVTable *pinfo_vtable;
6553 if (!System_Reflection_ParameterInfo_array) {
6556 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6557 mono_memory_barrier ();
6558 System_Reflection_ParameterInfo = klass;
6560 klass = mono_array_class_get (klass, 1);
6561 mono_memory_barrier ();
6562 System_Reflection_ParameterInfo_array = klass;
6565 if (!mono_method_signature (method)->param_count)
6566 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6568 /* Note: the cache is based on the address of the signature into the method
6569 * since we already cache MethodInfos with the method as keys.
6571 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6573 sig = mono_method_signature (method);
6574 member = mono_method_get_object (domain, method, refclass);
6575 names = g_new (char *, sig->param_count);
6576 mono_method_get_param_names (method, (const char **) names);
6578 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6579 mono_method_get_marshal_info (method, mspecs);
6581 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6582 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6583 for (i = 0; i < sig->param_count; ++i) {
6584 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6585 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6586 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6587 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6588 param->PositionImpl = i;
6589 param->AttrsImpl = sig->params [i]->attrs;
6591 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6592 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6593 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6595 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6599 blobs = g_new0 (char *, sig->param_count);
6600 types = g_new0 (guint32, sig->param_count);
6601 get_default_param_value_blobs (method, blobs, types);
6604 /* Build MonoType for the type from the Constant Table */
6606 type = g_new0 (MonoType, 1);
6607 type->type = types [i];
6608 type->data.klass = NULL;
6609 if (types [i] == MONO_TYPE_CLASS)
6610 type->data.klass = mono_defaults.object_class;
6611 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6612 /* For enums, types [i] contains the base type */
6614 type->type = MONO_TYPE_VALUETYPE;
6615 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6617 type->data.klass = mono_class_from_mono_type (type);
6619 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6621 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6622 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6623 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6624 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6626 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6632 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6634 mono_array_setref (res, i, param);
6641 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6643 mono_metadata_free_marshal_spec (mspecs [i]);
6646 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6650 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6652 return mono_param_get_objects_internal (domain, method, NULL);
6656 * mono_method_body_get_object:
6657 * @domain: an app domain
6660 * Return an System.Reflection.MethodBody object representing the method @method.
6662 MonoReflectionMethodBody*
6663 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6665 static MonoClass *System_Reflection_MethodBody = NULL;
6666 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6667 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6668 MonoReflectionMethodBody *ret;
6669 MonoMethodNormal *mn;
6670 MonoMethodHeader *header;
6671 guint32 method_rva, local_var_sig_token;
6673 unsigned char format, flags;
6676 if (!System_Reflection_MethodBody)
6677 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6678 if (!System_Reflection_LocalVariableInfo)
6679 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6680 if (!System_Reflection_ExceptionHandlingClause)
6681 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6683 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6685 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6686 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6687 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6688 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6690 mn = (MonoMethodNormal *)method;
6691 header = mono_method_get_header (method);
6693 /* Obtain local vars signature token */
6694 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6695 ptr = mono_image_rva_map (method->klass->image, method_rva);
6696 flags = *(const unsigned char *) ptr;
6697 format = flags & METHOD_HEADER_FORMAT_MASK;
6699 case METHOD_HEADER_TINY_FORMAT:
6700 local_var_sig_token = 0;
6702 case METHOD_HEADER_FAT_FORMAT:
6706 local_var_sig_token = read32 (ptr);
6709 g_assert_not_reached ();
6712 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6714 ret->init_locals = header->init_locals;
6715 ret->max_stack = header->max_stack;
6716 ret->local_var_sig_token = local_var_sig_token;
6717 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6718 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6721 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6722 for (i = 0; i < header->num_locals; ++i) {
6723 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6724 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6725 info->is_pinned = header->locals [i]->pinned;
6726 info->local_index = i;
6727 mono_array_setref (ret->locals, i, info);
6731 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6732 for (i = 0; i < header->num_clauses; ++i) {
6733 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6734 MonoExceptionClause *clause = &header->clauses [i];
6736 info->flags = clause->flags;
6737 info->try_offset = clause->try_offset;
6738 info->try_length = clause->try_len;
6739 info->handler_offset = clause->handler_offset;
6740 info->handler_length = clause->handler_len;
6741 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6742 info->filter_offset = clause->data.filter_offset;
6743 else if (clause->data.catch_class)
6744 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6746 mono_array_setref (ret->clauses, i, info);
6749 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6754 * mono_get_dbnull_object:
6755 * @domain: Domain where the object lives
6757 * Returns the System.DBNull.Value singleton object
6759 * Used as the value for ParameterInfo.DefaultValue
6762 mono_get_dbnull_object (MonoDomain *domain)
6765 static MonoClassField *dbnull_value_field = NULL;
6767 if (!dbnull_value_field) {
6768 MonoClass *dbnull_klass;
6769 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6770 mono_class_init (dbnull_klass);
6771 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6772 g_assert (dbnull_value_field);
6774 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6780 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6782 guint32 param_index, i, lastp, crow = 0;
6783 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6786 MonoClass *klass = method->klass;
6787 MonoImage *image = klass->image;
6788 MonoMethodSignature *methodsig = mono_method_signature (method);
6790 MonoTableInfo *constt;
6791 MonoTableInfo *methodt;
6792 MonoTableInfo *paramt;
6794 if (!methodsig->param_count)
6797 mono_class_init (klass);
6799 if (klass->image->dynamic) {
6800 MonoReflectionMethodAux *aux;
6801 if (method->is_inflated)
6802 method = ((MonoMethodInflated*)method)->declaring;
6803 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6804 if (aux && aux->param_defaults) {
6805 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6806 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6811 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6812 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6813 constt = &image->tables [MONO_TABLE_CONSTANT];
6815 idx = mono_method_get_index (method) - 1;
6816 g_assert (idx != -1);
6818 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6819 if (idx + 1 < methodt->rows)
6820 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6822 lastp = paramt->rows + 1;
6824 for (i = param_index; i < lastp; ++i) {
6827 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6828 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6830 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6833 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6838 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6839 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6840 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6847 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6852 MonoType *basetype = type;
6857 klass = mono_class_from_mono_type (type);
6858 if (klass->valuetype) {
6859 object = mono_object_new (domain, klass);
6860 retval = ((gchar *) object + sizeof (MonoObject));
6861 if (klass->enumtype)
6862 basetype = mono_class_enum_basetype (klass);
6867 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6874 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6878 memset (assembly, 0, sizeof (MonoAssemblyName));
6880 assembly->culture = "";
6881 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6883 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6886 while (g_ascii_isspace (*p) || *p == ',') {
6895 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6897 assembly->major = strtoul (p, &s, 10);
6898 if (s == p || *s != '.')
6901 assembly->minor = strtoul (p, &s, 10);
6902 if (s == p || *s != '.')
6905 assembly->build = strtoul (p, &s, 10);
6906 if (s == p || *s != '.')
6909 assembly->revision = strtoul (p, &s, 10);
6913 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6915 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6916 assembly->culture = "";
6919 assembly->culture = p;
6920 while (*p && *p != ',') {
6924 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6926 if (strncmp (p, "null", 4) == 0) {
6931 while (*p && *p != ',') {
6934 len = (p - start + 1);
6935 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6936 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6937 g_strlcpy ((char*)assembly->public_key_token, start, len);
6940 while (*p && *p != ',')
6944 while (g_ascii_isspace (*p) || *p == ',') {
6958 * mono_reflection_parse_type:
6961 * Parse a type name as accepted by the GetType () method and output the info
6962 * extracted in the info structure.
6963 * the name param will be mangled, so, make a copy before passing it to this function.
6964 * The fields in info will be valid until the memory pointed to by name is valid.
6966 * See also mono_type_get_name () below.
6968 * Returns: 0 on parse error.
6971 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6972 MonoTypeNameParse *info)
6974 char *start, *p, *w, *temp, *last_point, *startn;
6975 int in_modifiers = 0;
6976 int isbyref = 0, rank, arity = 0, i;
6978 start = p = w = name;
6980 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6981 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6982 info->name = info->name_space = NULL;
6983 info->nested = NULL;
6984 info->modifiers = NULL;
6985 info->type_arguments = NULL;
6987 /* last_point separates the namespace from the name */
6990 while (*p == ' ') p++, start++, w++, name++;
6995 *p = 0; /* NULL terminate the name */
6997 info->nested = g_list_append (info->nested, startn);
6998 /* we have parsed the nesting namespace + name */
7002 info->name_space = start;
7004 info->name = last_point + 1;
7006 info->name_space = (char *)"";
7025 i = strtol (p, &temp, 10);
7042 info->name_space = start;
7044 info->name = last_point + 1;
7046 info->name_space = (char *)"";
7053 if (isbyref) /* only one level allowed by the spec */
7056 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7060 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7066 info->type_arguments = g_ptr_array_new ();
7067 for (i = 0; i < arity; i++) {
7068 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7069 gboolean fqname = FALSE;
7071 g_ptr_array_add (info->type_arguments, subinfo);
7078 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7089 while (*p && (*p != ']'))
7097 if (g_ascii_isspace (*aname)) {
7104 !assembly_name_to_aname (&subinfo->assembly, aname))
7108 if (i + 1 < arity) {
7128 else if (*p == '*') /* '*' means unknown lower bound */
7129 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7136 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7147 if (g_ascii_isspace (*p)) {
7154 return 0; /* missing assembly name */
7155 if (!assembly_name_to_aname (&info->assembly, p))
7161 if (info->assembly.name)
7164 // *w = 0; /* terminate class name */
7166 if (!info->name || !*info->name)
7170 /* add other consistency checks */
7175 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7177 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7181 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7183 gboolean type_resolve = FALSE;
7185 MonoImage *rootimage = image;
7187 if (info->assembly.name) {
7188 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7189 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7191 * This could happen in the AOT compiler case when the search hook is not
7194 assembly = image->assembly;
7196 /* then we must load the assembly ourselve - see #60439 */
7197 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7201 image = assembly->image;
7202 } else if (!image) {
7203 image = mono_defaults.corlib;
7206 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7207 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7208 image = mono_defaults.corlib;
7209 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7216 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7221 gboolean bounded = FALSE;
7224 image = mono_defaults.corlib;
7227 klass = mono_class_from_name_case (image, info->name_space, info->name);
7229 klass = mono_class_from_name (image, info->name_space, info->name);
7232 for (mod = info->nested; mod; mod = mod->next) {
7233 gpointer iter = NULL;
7237 mono_class_init (parent);
7239 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7241 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7244 if (strcmp (klass->name, mod->data) == 0)
7253 mono_class_init (klass);
7255 if (info->type_arguments) {
7256 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7257 MonoReflectionType *the_type;
7261 for (i = 0; i < info->type_arguments->len; i++) {
7262 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7264 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7265 if (!type_args [i]) {
7271 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7273 instance = mono_reflection_bind_generic_parameters (
7274 the_type, info->type_arguments->len, type_args);
7280 klass = mono_class_from_mono_type (instance);
7283 for (mod = info->modifiers; mod; mod = mod->next) {
7284 modval = GPOINTER_TO_UINT (mod->data);
7285 if (!modval) { /* byref: must be last modifier */
7286 return &klass->this_arg;
7287 } else if (modval == -1) {
7288 klass = mono_ptr_class_get (&klass->byval_arg);
7289 } else if (modval == -2) {
7291 } else { /* array rank */
7292 klass = mono_bounded_array_class_get (klass, modval, bounded);
7294 mono_class_init (klass);
7297 return &klass->byval_arg;
7301 * mono_reflection_get_type:
7302 * @image: a metadata context
7303 * @info: type description structure
7304 * @ignorecase: flag for case-insensitive string compares
7305 * @type_resolve: whenever type resolve was already tried
7307 * Build a MonoType from the type description in @info.
7312 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7313 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7317 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7319 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7323 g_assert (assembly->dynamic);
7325 /* Enumerate all modules */
7328 if (abuilder->modules) {
7329 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7330 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7331 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7337 if (!type && abuilder->loaded_modules) {
7338 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7339 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7340 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7350 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7353 MonoReflectionAssembly *assembly;
7357 if (image && image->dynamic)
7358 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7360 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7363 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7370 *type_resolve = TRUE;
7373 /* Reconstruct the type name */
7374 fullName = g_string_new ("");
7375 if (info->name_space && (info->name_space [0] != '\0'))
7376 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7378 g_string_printf (fullName, "%s", info->name);
7379 for (mod = info->nested; mod; mod = mod->next)
7380 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7382 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7384 if (assembly->assembly->dynamic)
7385 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7387 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7390 g_string_free (fullName, TRUE);
7395 mono_reflection_free_type_info (MonoTypeNameParse *info)
7397 g_list_free (info->modifiers);
7398 g_list_free (info->nested);
7400 if (info->type_arguments) {
7403 for (i = 0; i < info->type_arguments->len; i++) {
7404 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7406 mono_reflection_free_type_info (subinfo);
7407 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7411 g_ptr_array_free (info->type_arguments, TRUE);
7416 * mono_reflection_type_from_name:
7418 * @image: a metadata context (can be NULL).
7420 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7421 * it defaults to get the type from @image or, if @image is NULL or loading
7422 * from it fails, uses corlib.
7426 mono_reflection_type_from_name (char *name, MonoImage *image)
7428 MonoType *type = NULL;
7429 MonoTypeNameParse info;
7432 /* Make a copy since parse_type modifies its argument */
7433 tmp = g_strdup (name);
7435 /*g_print ("requested type %s\n", str);*/
7436 if (mono_reflection_parse_type (tmp, &info)) {
7437 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7441 mono_reflection_free_type_info (&info);
7446 * mono_reflection_get_token:
7448 * Return the metadata token of OBJ which should be an object
7449 * representing a metadata element.
7452 mono_reflection_get_token (MonoObject *obj)
7457 klass = obj->vtable->klass;
7459 if (strcmp (klass->name, "MethodBuilder") == 0) {
7460 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7462 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7463 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7464 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7466 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7467 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7468 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7470 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7471 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7472 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7473 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7474 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7475 } else if (strcmp (klass->name, "MonoType") == 0) {
7476 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7477 token = mono_class_from_mono_type (type)->type_token;
7478 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7479 strcmp (klass->name, "MonoMethod") == 0 ||
7480 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7481 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7482 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7483 if (m->method->is_inflated) {
7484 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7485 return inflated->declaring->token;
7487 token = m->method->token;
7489 } else if (strcmp (klass->name, "MonoField") == 0) {
7490 MonoReflectionField *f = (MonoReflectionField*)obj;
7492 if (is_field_on_inst (f->field)) {
7493 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7494 int field_index = f->field - dgclass->fields;
7497 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7498 obj = dgclass->field_objects [field_index];
7499 return mono_reflection_get_token (obj);
7501 token = mono_class_get_field_token (f->field);
7502 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7503 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7505 token = mono_class_get_property_token (p->property);
7506 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7507 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7509 token = mono_class_get_event_token (p->event);
7510 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7511 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7513 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7514 } else if (strcmp (klass->name, "Module") == 0) {
7515 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7518 } else if (strcmp (klass->name, "Assembly") == 0) {
7519 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7521 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7522 MonoException *ex = mono_get_exception_not_implemented (msg);
7524 mono_raise_exception (ex);
7531 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7533 int slen, type = t->type;
7534 MonoClass *tklass = t->data.klass;
7540 case MONO_TYPE_BOOLEAN: {
7541 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7546 case MONO_TYPE_CHAR:
7548 case MONO_TYPE_I2: {
7549 guint16 *val = g_malloc (sizeof (guint16));
7554 #if SIZEOF_VOID_P == 4
7560 case MONO_TYPE_I4: {
7561 guint32 *val = g_malloc (sizeof (guint32));
7566 #if SIZEOF_VOID_P == 8
7567 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7571 case MONO_TYPE_I8: {
7572 guint64 *val = g_malloc (sizeof (guint64));
7577 case MONO_TYPE_R8: {
7578 double *val = g_malloc (sizeof (double));
7583 case MONO_TYPE_VALUETYPE:
7584 if (t->data.klass->enumtype) {
7585 type = mono_class_enum_basetype (t->data.klass)->type;
7588 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7591 case MONO_TYPE_STRING:
7592 if (*p == (char)0xFF) {
7596 slen = mono_metadata_decode_value (p, &p);
7598 return mono_string_new_len (mono_domain_get (), p, slen);
7599 case MONO_TYPE_CLASS: {
7602 if (*p == (char)0xFF) {
7607 slen = mono_metadata_decode_value (p, &p);
7608 n = g_memdup (p, slen + 1);
7610 t = mono_reflection_type_from_name (n, image);
7612 g_warning ("Cannot load type '%s'", n);
7616 return mono_type_get_object (mono_domain_get (), t);
7620 case MONO_TYPE_OBJECT: {
7623 MonoClass *subc = NULL;
7628 } else if (subt == 0x0E) {
7629 type = MONO_TYPE_STRING;
7631 } else if (subt == 0x1D) {
7632 MonoType simple_type = {{0}};
7637 /* See Partition II, Appendix B3 */
7638 etype = MONO_TYPE_OBJECT;
7639 type = MONO_TYPE_SZARRAY;
7640 simple_type.type = etype;
7641 tklass = mono_class_from_mono_type (&simple_type);
7643 } else if (subt == 0x55) {
7646 slen = mono_metadata_decode_value (p, &p);
7647 n = g_memdup (p, slen + 1);
7649 t = mono_reflection_type_from_name (n, image);
7651 g_error ("Cannot load type '%s'", n);
7654 subc = mono_class_from_mono_type (t);
7655 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7656 MonoType simple_type = {{0}};
7657 simple_type.type = subt;
7658 subc = mono_class_from_mono_type (&simple_type);
7660 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7662 val = load_cattr_value (image, &subc->byval_arg, p, end);
7663 obj = mono_object_new (mono_domain_get (), subc);
7664 g_assert (!subc->has_references);
7665 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7669 case MONO_TYPE_SZARRAY: {
7671 guint32 i, alen, basetype;
7674 if (alen == 0xffffffff) {
7678 arr = mono_array_new (mono_domain_get(), tklass, alen);
7679 basetype = tklass->byval_arg.type;
7680 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7681 basetype = mono_class_enum_basetype (tklass)->type;
7686 case MONO_TYPE_BOOLEAN:
7687 for (i = 0; i < alen; i++) {
7688 MonoBoolean val = *p++;
7689 mono_array_set (arr, MonoBoolean, i, val);
7692 case MONO_TYPE_CHAR:
7695 for (i = 0; i < alen; i++) {
7696 guint16 val = read16 (p);
7697 mono_array_set (arr, guint16, i, val);
7704 for (i = 0; i < alen; i++) {
7705 guint32 val = read32 (p);
7706 mono_array_set (arr, guint32, i, val);
7711 for (i = 0; i < alen; i++) {
7714 mono_array_set (arr, double, i, val);
7720 for (i = 0; i < alen; i++) {
7721 guint64 val = read64 (p);
7722 mono_array_set (arr, guint64, i, val);
7726 case MONO_TYPE_CLASS:
7727 case MONO_TYPE_OBJECT:
7728 case MONO_TYPE_STRING:
7729 for (i = 0; i < alen; i++) {
7730 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7731 mono_array_setref (arr, i, item);
7735 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7741 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7747 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7749 static MonoClass *klass;
7750 static MonoMethod *ctor;
7752 void *params [2], *unboxed;
7755 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7757 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7759 params [0] = mono_type_get_object (mono_domain_get (), t);
7761 retval = mono_object_new (mono_domain_get (), klass);
7762 unboxed = mono_object_unbox (retval);
7763 mono_runtime_invoke (ctor, unboxed, params, NULL);
7769 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7771 static MonoClass *klass;
7772 static MonoMethod *ctor;
7774 void *unboxed, *params [2];
7777 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7779 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7782 params [1] = typedarg;
7783 retval = mono_object_new (mono_domain_get (), klass);
7784 unboxed = mono_object_unbox (retval);
7785 mono_runtime_invoke (ctor, unboxed, params, NULL);
7791 type_is_reference (MonoType *type)
7793 switch (type->type) {
7794 case MONO_TYPE_BOOLEAN:
7795 case MONO_TYPE_CHAR:
7808 case MONO_TYPE_VALUETYPE:
7816 free_param_data (MonoMethodSignature *sig, void **params) {
7818 for (i = 0; i < sig->param_count; ++i) {
7819 if (!type_is_reference (sig->params [i]))
7820 g_free (params [i]);
7825 * Find the field index in the metadata FieldDef table.
7828 find_field_index (MonoClass *klass, MonoClassField *field) {
7831 for (i = 0; i < klass->field.count; ++i) {
7832 if (field == &klass->fields [i])
7833 return klass->field.first + 1 + i;
7839 * Find the property index in the metadata Property table.
7842 find_property_index (MonoClass *klass, MonoProperty *property) {
7845 for (i = 0; i < klass->ext->property.count; ++i) {
7846 if (property == &klass->ext->properties [i])
7847 return klass->ext->property.first + 1 + i;
7853 * Find the event index in the metadata Event table.
7856 find_event_index (MonoClass *klass, MonoEvent *event) {
7859 for (i = 0; i < klass->ext->event.count; ++i) {
7860 if (event == &klass->ext->events [i])
7861 return klass->ext->event.first + 1 + i;
7867 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7869 const char *p = (const char*)data;
7871 guint32 i, j, num_named;
7873 void *params_buf [32];
7875 MonoMethodSignature *sig;
7877 mono_class_init (method->klass);
7880 attr = mono_object_new (mono_domain_get (), method->klass);
7881 mono_runtime_invoke (method, attr, NULL, NULL);
7885 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7888 /*g_print ("got attr %s\n", method->klass->name);*/
7890 sig = mono_method_signature (method);
7891 if (sig->param_count < 32)
7892 params = params_buf;
7894 /* Allocate using GC so it gets GC tracking */
7895 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7899 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7900 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7904 attr = mono_object_new (mono_domain_get (), method->klass);
7905 mono_runtime_invoke (method, attr, params, NULL);
7906 free_param_data (method->signature, params);
7907 num_named = read16 (named);
7909 for (j = 0; j < num_named; j++) {
7911 char *name, named_type, data_type;
7912 named_type = *named++;
7913 data_type = *named++; /* type of data */
7914 if (data_type == MONO_TYPE_SZARRAY)
7915 data_type = *named++;
7916 if (data_type == MONO_TYPE_ENUM) {
7919 type_len = mono_metadata_decode_blob_size (named, &named);
7920 type_name = g_malloc (type_len + 1);
7921 memcpy (type_name, named, type_len);
7922 type_name [type_len] = 0;
7924 /* FIXME: lookup the type and check type consistency */
7927 name_len = mono_metadata_decode_blob_size (named, &named);
7928 name = g_malloc (name_len + 1);
7929 memcpy (name, named, name_len);
7930 name [name_len] = 0;
7932 if (named_type == 0x53) {
7933 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7934 void *val = load_cattr_value (image, field->type, named, &named);
7935 mono_field_set_value (attr, field, val);
7936 if (!type_is_reference (field->type))
7938 } else if (named_type == 0x54) {
7941 MonoType *prop_type;
7943 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7944 /* can we have more that 1 arg in a custom attr named property? */
7945 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7946 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7947 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7948 mono_property_set_value (prop, attr, pparams, NULL);
7949 if (!type_is_reference (prop_type))
7950 g_free (pparams [0]);
7955 if (params != params_buf)
7956 mono_gc_free_fixed (params);
7962 * mono_reflection_create_custom_attr_data_args:
7964 * Create an array of typed and named arguments from the cattr blob given by DATA.
7965 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
7966 * NAMED_ARG_INFO will contain information about the named arguments.
7969 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)
7971 MonoArray *typedargs, *namedargs;
7972 MonoClass *attrklass;
7974 const char *p = (const char*)data;
7976 guint32 i, j, num_named;
7977 CattrNamedArg *arginfo = NULL;
7979 mono_class_init (method->klass);
7983 *named_arg_info = NULL;
7985 domain = mono_domain_get ();
7987 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7990 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7994 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7998 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7999 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8000 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8001 mono_array_setref (typedargs, i, obj);
8003 if (!type_is_reference (mono_method_signature (method)->params [i]))
8008 num_named = read16 (named);
8009 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8011 attrklass = method->klass;
8013 arginfo = g_new0 (CattrNamedArg, num_named);
8014 *named_arg_info = arginfo;
8016 for (j = 0; j < num_named; j++) {
8018 char *name, named_type, data_type;
8019 named_type = *named++;
8020 data_type = *named++; /* type of data */
8021 if (data_type == MONO_TYPE_SZARRAY)
8022 data_type = *named++;
8023 if (data_type == MONO_TYPE_ENUM) {
8026 type_len = mono_metadata_decode_blob_size (named, &named);
8027 type_name = g_malloc (type_len + 1);
8028 memcpy (type_name, named, type_len);
8029 type_name [type_len] = 0;
8031 /* FIXME: lookup the type and check type consistency */
8034 name_len = mono_metadata_decode_blob_size (named, &named);
8035 name = g_malloc (name_len + 1);
8036 memcpy (name, named, name_len);
8037 name [name_len] = 0;
8039 if (named_type == 0x53) {
8041 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8044 arginfo [j].type = field->type;
8045 arginfo [j].field = field;
8047 val = load_cattr_value (image, field->type, named, &named);
8048 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8049 mono_array_setref (namedargs, j, obj);
8050 if (!type_is_reference (field->type))
8052 } else if (named_type == 0x54) {
8054 MonoType *prop_type;
8055 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8058 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8059 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8061 arginfo [j].type = prop_type;
8062 arginfo [j].prop = prop;
8064 val = load_cattr_value (image, prop_type, named, &named);
8065 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8066 mono_array_setref (namedargs, j, obj);
8067 if (!type_is_reference (prop_type))
8073 *typed_args = typedargs;
8074 *named_args = namedargs;
8078 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8080 MonoArray *typedargs, *namedargs;
8081 static MonoMethod *ctor;
8085 CattrNamedArg *arginfo;
8088 mono_class_init (method->klass);
8091 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8093 domain = mono_domain_get ();
8095 /* This is for Attributes with no parameters */
8096 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8097 params [0] = mono_method_get_object (domain, method, NULL);
8098 params [1] = params [2] = NULL;
8099 mono_runtime_invoke (method, attr, params, NULL);
8103 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8104 if (!typedargs || !namedargs)
8107 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8108 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8109 MonoObject *typedarg;
8111 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8112 mono_array_setref (typedargs, i, typedarg);
8115 for (i = 0; i < mono_array_length (namedargs); ++i) {
8116 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8117 MonoObject *typedarg, *namedarg, *minfo;
8119 if (arginfo [i].prop)
8120 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8122 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8124 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8125 namedarg = create_cattr_named_arg (minfo, typedarg);
8127 mono_array_setref (namedargs, i, namedarg);
8130 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8131 params [0] = mono_method_get_object (domain, method, NULL);
8132 params [1] = typedargs;
8133 params [2] = namedargs;
8134 mono_runtime_invoke (ctor, attr, params, NULL);
8139 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8145 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8146 for (i = 0; i < cinfo->num_attrs; ++i) {
8147 if (!cinfo->attrs [i].ctor)
8148 /* The cattr type is not finished yet */
8149 /* We should include the type name but cinfo doesn't contain it */
8150 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8151 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8152 mono_array_setref (result, i, attr);
8158 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8165 for (i = 0; i < cinfo->num_attrs; ++i) {
8166 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8170 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8172 for (i = 0; i < cinfo->num_attrs; ++i) {
8173 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8174 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8175 mono_array_setref (result, n, attr);
8183 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8189 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8190 for (i = 0; i < cinfo->num_attrs; ++i) {
8191 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8192 mono_array_setref (result, i, attr);
8198 * mono_custom_attrs_from_index:
8200 * Returns: NULL if no attributes are found or if a loading error occurs.
8203 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8205 guint32 mtoken, i, len;
8206 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8208 MonoCustomAttrInfo *ainfo;
8209 GList *tmp, *list = NULL;
8212 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8214 i = mono_metadata_custom_attrs_from_index (image, idx);
8218 while (i < ca->rows) {
8219 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8221 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8224 len = g_list_length (list);
8227 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8228 ainfo->num_attrs = len;
8229 ainfo->image = image;
8230 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8231 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8232 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8233 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8234 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8235 mtoken |= MONO_TOKEN_METHOD_DEF;
8237 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8238 mtoken |= MONO_TOKEN_MEMBER_REF;
8241 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8244 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8245 if (!ainfo->attrs [i].ctor) {
8246 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8251 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8252 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8253 ainfo->attrs [i].data = (guchar*)data;
8261 mono_custom_attrs_from_method (MonoMethod *method)
8266 * An instantiated method has the same cattrs as the generic method definition.
8268 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8269 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8271 if (method->is_inflated)
8272 method = ((MonoMethodInflated *) method)->declaring;
8274 if (method->dynamic || method->klass->image->dynamic)
8275 return lookup_custom_attr (method->klass->image, method);
8278 /* Synthetic methods */
8281 idx = mono_method_get_index (method);
8282 idx <<= MONO_CUSTOM_ATTR_BITS;
8283 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8284 return mono_custom_attrs_from_index (method->klass->image, idx);
8288 mono_custom_attrs_from_class (MonoClass *klass)
8292 if (klass->generic_class)
8293 klass = klass->generic_class->container_class;
8295 if (klass->image->dynamic)
8296 return lookup_custom_attr (klass->image, klass);
8298 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8299 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8300 idx <<= MONO_CUSTOM_ATTR_BITS;
8301 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8303 idx = mono_metadata_token_index (klass->type_token);
8304 idx <<= MONO_CUSTOM_ATTR_BITS;
8305 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8307 return mono_custom_attrs_from_index (klass->image, idx);
8311 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8315 if (assembly->image->dynamic)
8316 return lookup_custom_attr (assembly->image, assembly);
8317 idx = 1; /* there is only one assembly */
8318 idx <<= MONO_CUSTOM_ATTR_BITS;
8319 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8320 return mono_custom_attrs_from_index (assembly->image, idx);
8323 static MonoCustomAttrInfo*
8324 mono_custom_attrs_from_module (MonoImage *image)
8329 return lookup_custom_attr (image, image);
8330 idx = 1; /* there is only one module */
8331 idx <<= MONO_CUSTOM_ATTR_BITS;
8332 idx |= MONO_CUSTOM_ATTR_MODULE;
8333 return mono_custom_attrs_from_index (image, idx);
8337 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8341 if (klass->image->dynamic) {
8342 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8343 return lookup_custom_attr (klass->image, property);
8345 idx = find_property_index (klass, property);
8346 idx <<= MONO_CUSTOM_ATTR_BITS;
8347 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8348 return mono_custom_attrs_from_index (klass->image, idx);
8352 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8356 if (klass->image->dynamic) {
8357 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8358 return lookup_custom_attr (klass->image, event);
8360 idx = find_event_index (klass, event);
8361 idx <<= MONO_CUSTOM_ATTR_BITS;
8362 idx |= MONO_CUSTOM_ATTR_EVENT;
8363 return mono_custom_attrs_from_index (klass->image, idx);
8367 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8370 if (klass->image->dynamic) {
8371 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8372 return lookup_custom_attr (klass->image, field);
8374 idx = find_field_index (klass, field);
8375 idx <<= MONO_CUSTOM_ATTR_BITS;
8376 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8377 return mono_custom_attrs_from_index (klass->image, idx);
8381 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8384 guint32 i, idx, method_index;
8385 guint32 param_list, param_last, param_pos, found;
8387 MonoReflectionMethodAux *aux;
8390 * An instantiated method has the same cattrs as the generic method definition.
8392 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8393 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8395 if (method->is_inflated)
8396 method = ((MonoMethodInflated *) method)->declaring;
8398 if (method->klass->image->dynamic) {
8399 MonoCustomAttrInfo *res, *ainfo;
8402 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8403 if (!aux || !aux->param_cattr)
8406 /* Need to copy since it will be freed later */
8407 ainfo = aux->param_cattr [param];
8408 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8409 res = g_malloc0 (size);
8410 memcpy (res, ainfo, size);
8414 image = method->klass->image;
8415 method_index = mono_method_get_index (method);
8416 ca = &image->tables [MONO_TABLE_METHOD];
8418 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8419 if (method_index == ca->rows) {
8420 ca = &image->tables [MONO_TABLE_PARAM];
8421 param_last = ca->rows + 1;
8423 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8424 ca = &image->tables [MONO_TABLE_PARAM];
8427 for (i = param_list; i < param_last; ++i) {
8428 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8429 if (param_pos == param) {
8437 idx <<= MONO_CUSTOM_ATTR_BITS;
8438 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8439 return mono_custom_attrs_from_index (image, idx);
8443 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8447 for (i = 0; i < ainfo->num_attrs; ++i) {
8448 klass = ainfo->attrs [i].ctor->klass;
8449 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8456 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8463 for (i = 0; i < ainfo->num_attrs; ++i) {
8464 klass = ainfo->attrs [i].ctor->klass;
8465 if (mono_class_has_parent (klass, attr_klass)) {
8470 if (attr_index == -1)
8473 attrs = mono_custom_attrs_construct (ainfo);
8475 return mono_array_get (attrs, MonoObject*, attr_index);
8481 * mono_reflection_get_custom_attrs_info:
8482 * @obj: a reflection object handle
8484 * Return the custom attribute info for attributes defined for the
8485 * reflection handle @obj. The objects.
8487 * FIXME this function leaks like a sieve for SRE objects.
8490 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8493 MonoCustomAttrInfo *cinfo = NULL;
8495 klass = obj->vtable->klass;
8496 if (klass == mono_defaults.monotype_class) {
8497 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8498 klass = mono_class_from_mono_type (type);
8499 cinfo = mono_custom_attrs_from_class (klass);
8500 } else if (strcmp ("Assembly", klass->name) == 0) {
8501 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8502 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8503 } else if (strcmp ("Module", klass->name) == 0) {
8504 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8505 cinfo = mono_custom_attrs_from_module (module->image);
8506 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8507 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8508 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8509 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8510 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8511 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8512 } else if (strcmp ("MonoField", klass->name) == 0) {
8513 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8514 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8515 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8516 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8517 cinfo = mono_custom_attrs_from_method (rmethod->method);
8518 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8519 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8520 cinfo = mono_custom_attrs_from_method (rmethod->method);
8521 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8522 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8523 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8524 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8525 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8526 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8527 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8528 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8529 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8530 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8531 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8532 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8533 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8534 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8535 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8536 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8537 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8538 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8539 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8540 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8541 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8542 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8543 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8544 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8545 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8546 } else { /* handle other types here... */
8547 g_error ("get custom attrs not yet supported for %s", klass->name);
8554 * mono_reflection_get_custom_attrs_by_type:
8555 * @obj: a reflection object handle
8557 * Return an array with all the custom attributes defined of the
8558 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8559 * of that type are returned. The objects are fully build. Return NULL if a loading error
8563 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8566 MonoCustomAttrInfo *cinfo;
8568 cinfo = mono_reflection_get_custom_attrs_info (obj);
8571 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8573 result = mono_custom_attrs_construct (cinfo);
8575 mono_custom_attrs_free (cinfo);
8577 if (mono_loader_get_last_error ())
8579 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8586 * mono_reflection_get_custom_attrs:
8587 * @obj: a reflection object handle
8589 * Return an array with all the custom attributes defined of the
8590 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8594 mono_reflection_get_custom_attrs (MonoObject *obj)
8596 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8600 * mono_reflection_get_custom_attrs_data:
8601 * @obj: a reflection obj handle
8603 * Returns an array of System.Reflection.CustomAttributeData,
8604 * which include information about attributes reflected on
8605 * types loaded using the Reflection Only methods
8608 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8611 MonoCustomAttrInfo *cinfo;
8613 cinfo = mono_reflection_get_custom_attrs_info (obj);
8615 result = mono_custom_attrs_data_construct (cinfo);
8617 mono_custom_attrs_free (cinfo);
8619 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8624 static MonoReflectionType*
8625 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8627 MonoMethod *method_get_underlying_system_type;
8629 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8630 mono_class_get_method_from_name (mono_object_class (t),
8631 "get_UnderlyingSystemType",
8633 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8636 #ifndef DISABLE_REFLECTION_EMIT
8639 is_corlib_type (MonoClass *class)
8641 return class->image == mono_defaults.corlib;
8645 is_usertype (MonoReflectionType *ref)
8647 MonoClass *class = mono_object_class (ref);
8648 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8651 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8652 static MonoClass *cached_class; \
8654 return cached_class == _class; \
8655 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8656 cached_class = _class; \
8663 is_sre_array (MonoClass *class)
8665 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8669 is_sre_byref (MonoClass *class)
8671 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8675 is_sre_pointer (MonoClass *class)
8677 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8681 is_sre_generic_instance (MonoClass *class)
8683 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8687 mono_reflection_type_get_handle (MonoReflectionType* ref)
8695 if (is_usertype (ref)) {
8696 ref = mono_reflection_type_get_underlying_system_type (ref);
8697 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8702 class = mono_object_class (ref);
8704 if (is_sre_array (class)) {
8706 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8707 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8709 if (sre_array->rank == 0) //single dimentional array
8710 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8712 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8713 sre_array->type.type = res;
8715 } else if (is_sre_byref (class)) {
8717 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8718 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8720 res = &mono_class_from_mono_type (base)->this_arg;
8721 sre_byref->type.type = res;
8723 } else if (is_sre_pointer (class)) {
8725 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8726 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8728 res = &mono_ptr_class_get (base)->byval_arg;
8729 sre_pointer->type.type = res;
8731 } else if (is_sre_generic_instance (class)) {
8732 MonoType *res, **types;
8733 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8736 count = mono_array_length (gclass->type_arguments);
8737 types = g_new0 (MonoType*, count);
8738 for (i = 0; i < count; ++i) {
8739 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8740 types [i] = mono_reflection_type_get_handle (t);
8743 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8746 gclass->type.type = res;
8750 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8754 static MonoReflectionType*
8755 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8757 if (!type || type->type)
8760 if (is_usertype (type)) {
8761 type = mono_reflection_type_get_underlying_system_type (type);
8762 if (is_usertype (type))
8763 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8770 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8772 mono_reflection_type_get_handle (type);
8776 * LOCKING: Assumes the loader lock is held.
8778 static MonoMethodSignature*
8779 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8780 MonoMethodSignature *sig;
8783 count = parameters? mono_array_length (parameters): 0;
8785 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8786 sig->param_count = count;
8787 sig->sentinelpos = -1; /* FIXME */
8788 for (i = 0; i < count; ++i)
8789 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8794 * LOCKING: Assumes the loader lock is held.
8796 static MonoMethodSignature*
8797 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8798 MonoMethodSignature *sig;
8800 sig = parameters_to_signature (image, ctor->parameters);
8801 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8802 sig->ret = &mono_defaults.void_class->byval_arg;
8807 * LOCKING: Assumes the loader lock is held.
8809 static MonoMethodSignature*
8810 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8811 MonoMethodSignature *sig;
8813 sig = parameters_to_signature (image, method->parameters);
8814 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8815 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8816 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8820 static MonoMethodSignature*
8821 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8822 MonoMethodSignature *sig;
8824 sig = parameters_to_signature (NULL, method->parameters);
8825 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8826 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8827 sig->generic_param_count = 0;
8832 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8834 MonoClass *klass = mono_object_class (prop);
8835 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8836 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8837 *name = mono_string_to_utf8 (pb->name);
8838 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8840 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8841 *name = g_strdup (p->property->name);
8842 if (p->property->get)
8843 *type = mono_method_signature (p->property->get)->ret;
8845 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8850 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8852 MonoClass *klass = mono_object_class (field);
8853 if (strcmp (klass->name, "FieldBuilder") == 0) {
8854 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8855 *name = mono_string_to_utf8 (fb->name);
8856 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8858 MonoReflectionField *f = (MonoReflectionField *)field;
8859 *name = g_strdup (mono_field_get_name (f->field));
8860 *type = f->field->type;
8863 #endif /* !DISABLE_REFLECTION_EMIT */
8866 * Encode a value in a custom attribute stream of bytes.
8867 * The value to encode is either supplied as an object in argument val
8868 * (valuetypes are boxed), or as a pointer to the data in the
8870 * @type represents the type of the value
8871 * @buffer is the start of the buffer
8872 * @p the current position in the buffer
8873 * @buflen contains the size of the buffer and is used to return the new buffer size
8874 * if this needs to be realloced.
8875 * @retbuffer and @retp return the start and the position of the buffer
8878 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8880 MonoTypeEnum simple_type;
8882 if ((p-buffer) + 10 >= *buflen) {
8885 newbuf = g_realloc (buffer, *buflen);
8886 p = newbuf + (p-buffer);
8890 argval = ((char*)arg + sizeof (MonoObject));
8891 simple_type = type->type;
8893 switch (simple_type) {
8894 case MONO_TYPE_BOOLEAN:
8899 case MONO_TYPE_CHAR:
8902 swap_with_size (p, argval, 2, 1);
8908 swap_with_size (p, argval, 4, 1);
8912 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8922 swap_with_size (p, argval, 8, 1);
8928 swap_with_size (p, argval, 8, 1);
8931 case MONO_TYPE_VALUETYPE:
8932 if (type->data.klass->enumtype) {
8933 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8936 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8939 case MONO_TYPE_STRING: {
8946 str = mono_string_to_utf8 ((MonoString*)arg);
8947 slen = strlen (str);
8948 if ((p-buffer) + 10 + slen >= *buflen) {
8952 newbuf = g_realloc (buffer, *buflen);
8953 p = newbuf + (p-buffer);
8956 mono_metadata_encode_value (slen, p, &p);
8957 memcpy (p, str, slen);
8962 case MONO_TYPE_CLASS: {
8970 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8971 slen = strlen (str);
8972 if ((p-buffer) + 10 + slen >= *buflen) {
8976 newbuf = g_realloc (buffer, *buflen);
8977 p = newbuf + (p-buffer);
8980 mono_metadata_encode_value (slen, p, &p);
8981 memcpy (p, str, slen);
8986 case MONO_TYPE_SZARRAY: {
8988 MonoClass *eclass, *arg_eclass;
8991 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8994 len = mono_array_length ((MonoArray*)arg);
8996 *p++ = (len >> 8) & 0xff;
8997 *p++ = (len >> 16) & 0xff;
8998 *p++ = (len >> 24) & 0xff;
9000 *retbuffer = buffer;
9001 eclass = type->data.klass;
9002 arg_eclass = mono_object_class (arg)->element_class;
9005 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9006 eclass = mono_defaults.object_class;
9008 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9009 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9010 int elsize = mono_class_array_element_size (arg_eclass);
9011 for (i = 0; i < len; ++i) {
9012 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9015 } else if (eclass->valuetype && arg_eclass->valuetype) {
9016 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9017 int elsize = mono_class_array_element_size (eclass);
9018 for (i = 0; i < len; ++i) {
9019 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9023 for (i = 0; i < len; ++i) {
9024 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9029 case MONO_TYPE_OBJECT: {
9035 * The parameter type is 'object' but the type of the actual
9036 * argument is not. So we have to add type information to the blob
9037 * too. This is completely undocumented in the spec.
9041 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9046 klass = mono_object_class (arg);
9048 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9051 } else if (klass->enumtype) {
9053 } else if (klass == mono_defaults.string_class) {
9054 simple_type = MONO_TYPE_STRING;
9057 } else if (klass->rank == 1) {
9059 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9060 /* See Partition II, Appendix B3 */
9063 *p++ = klass->element_class->byval_arg.type;
9064 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9066 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9067 *p++ = simple_type = klass->byval_arg.type;
9070 g_error ("unhandled type in custom attr");
9072 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9073 slen = strlen (str);
9074 if ((p-buffer) + 10 + slen >= *buflen) {
9078 newbuf = g_realloc (buffer, *buflen);
9079 p = newbuf + (p-buffer);
9082 mono_metadata_encode_value (slen, p, &p);
9083 memcpy (p, str, slen);
9086 simple_type = mono_class_enum_basetype (klass)->type;
9090 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9093 *retbuffer = buffer;
9097 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9099 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9100 char *str = type_get_qualified_name (type, NULL);
9101 int slen = strlen (str);
9105 * This seems to be optional...
9108 mono_metadata_encode_value (slen, p, &p);
9109 memcpy (p, str, slen);
9112 } else if (type->type == MONO_TYPE_OBJECT) {
9114 } else if (type->type == MONO_TYPE_CLASS) {
9115 /* it should be a type: encode_cattr_value () has the check */
9118 mono_metadata_encode_value (type->type, p, &p);
9119 if (type->type == MONO_TYPE_SZARRAY)
9120 /* See the examples in Partition VI, Annex B */
9121 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9127 #ifndef DISABLE_REFLECTION_EMIT
9129 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9132 /* Preallocate a large enough buffer */
9133 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9134 char *str = type_get_qualified_name (type, NULL);
9137 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9138 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9144 len += strlen (name);
9146 if ((p-buffer) + 20 + len >= *buflen) {
9150 newbuf = g_realloc (buffer, *buflen);
9151 p = newbuf + (p-buffer);
9155 encode_field_or_prop_type (type, p, &p);
9157 len = strlen (name);
9158 mono_metadata_encode_value (len, p, &p);
9159 memcpy (p, name, len);
9161 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9163 *retbuffer = buffer;
9167 * mono_reflection_get_custom_attrs_blob:
9168 * @ctor: custom attribute constructor
9169 * @ctorArgs: arguments o the constructor
9175 * Creates the blob of data that needs to be saved in the metadata and that represents
9176 * the custom attributed described by @ctor, @ctorArgs etc.
9177 * Returns: a Byte array representing the blob of data.
9180 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9183 MonoMethodSignature *sig;
9188 MONO_ARCH_SAVE_REGS;
9190 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9191 /* sig is freed later so allocate it in the heap */
9192 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9194 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9197 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9199 p = buffer = g_malloc (buflen);
9200 /* write the prolog */
9203 for (i = 0; i < sig->param_count; ++i) {
9204 arg = mono_array_get (ctorArgs, MonoObject*, i);
9205 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9209 i += mono_array_length (properties);
9211 i += mono_array_length (fields);
9213 *p++ = (i >> 8) & 0xff;
9216 for (i = 0; i < mono_array_length (properties); ++i) {
9220 prop = mono_array_get (properties, gpointer, i);
9221 get_prop_name_and_type (prop, &pname, &ptype);
9222 *p++ = 0x54; /* PROPERTY signature */
9223 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9230 for (i = 0; i < mono_array_length (fields); ++i) {
9234 field = mono_array_get (fields, gpointer, i);
9235 get_field_name_and_type (field, &fname, &ftype);
9236 *p++ = 0x53; /* FIELD signature */
9237 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9242 g_assert (p - buffer <= buflen);
9243 buflen = p - buffer;
9244 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9245 p = mono_array_addr (result, char, 0);
9246 memcpy (p, buffer, buflen);
9248 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9254 * mono_reflection_setup_internal_class:
9255 * @tb: a TypeBuilder object
9257 * Creates a MonoClass that represents the TypeBuilder.
9258 * This is a trick that lets us simplify a lot of reflection code
9259 * (and will allow us to support Build and Run assemblies easier).
9262 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9264 MonoClass *klass, *parent;
9266 MONO_ARCH_SAVE_REGS;
9268 RESOLVE_TYPE (tb->parent);
9270 mono_loader_lock ();
9273 /* check so we can compile corlib correctly */
9274 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9275 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9276 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9278 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9284 /* the type has already being created: it means we just have to change the parent */
9285 if (tb->type.type) {
9286 klass = mono_class_from_mono_type (tb->type.type);
9287 klass->parent = NULL;
9288 /* fool mono_class_setup_parent */
9289 klass->supertypes = NULL;
9290 mono_class_setup_parent (klass, parent);
9291 mono_class_setup_mono_type (klass);
9292 mono_loader_unlock ();
9296 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9298 klass->image = &tb->module->dynamic_image->image;
9300 klass->inited = 1; /* we lie to the runtime */
9301 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9302 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9303 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9304 klass->flags = tb->attrs;
9306 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9308 klass->element_class = klass;
9310 MOVING_GC_REGISTER (&klass->reflection_info);
9311 klass->reflection_info = tb;
9313 /* Put into cache so mono_class_get () will find it */
9314 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9316 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9317 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9319 if (parent != NULL) {
9320 mono_class_setup_parent (klass, parent);
9321 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9322 const char *old_n = klass->name;
9323 /* trick to get relative numbering right when compiling corlib */
9324 klass->name = "BuildingObject";
9325 mono_class_setup_parent (klass, mono_defaults.object_class);
9326 klass->name = old_n;
9329 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9330 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9331 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9332 klass->instance_size = sizeof (MonoObject);
9333 klass->size_inited = 1;
9334 mono_class_setup_vtable_general (klass, NULL, 0);
9337 mono_class_setup_mono_type (klass);
9339 mono_class_setup_supertypes (klass);
9342 * FIXME: handle interfaces.
9345 tb->type.type = &klass->byval_arg;
9347 if (tb->nesting_type) {
9348 g_assert (tb->nesting_type->type);
9349 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9352 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9354 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9356 mono_loader_unlock ();
9360 * mono_reflection_setup_generic_class:
9361 * @tb: a TypeBuilder object
9363 * Setup the generic class before adding the first generic parameter.
9366 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9371 * mono_reflection_create_generic_class:
9372 * @tb: a TypeBuilder object
9374 * Creates the generic class after all generic parameters have been added.
9377 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9382 MONO_ARCH_SAVE_REGS;
9384 klass = mono_class_from_mono_type (tb->type.type);
9386 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9388 if (klass->generic_container || (count == 0))
9391 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9393 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9395 klass->generic_container->owner.klass = klass;
9396 klass->generic_container->type_argc = count;
9397 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9399 klass->is_generic = 1;
9401 for (i = 0; i < count; i++) {
9402 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9403 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9404 klass->generic_container->type_params [i] = *param;
9405 /*Make sure we are a diferent type instance */
9406 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9407 klass->generic_container->type_params [i].info.pklass = NULL;
9409 g_assert (klass->generic_container->type_params [i].param.owner);
9412 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9416 * mono_reflection_create_internal_class:
9417 * @tb: a TypeBuilder object
9419 * Actually create the MonoClass that is associated with the TypeBuilder.
9422 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9426 MONO_ARCH_SAVE_REGS;
9428 klass = mono_class_from_mono_type (tb->type.type);
9430 mono_loader_lock ();
9431 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9432 MonoReflectionFieldBuilder *fb;
9434 MonoType *enum_basetype;
9436 g_assert (tb->fields != NULL);
9437 g_assert (mono_array_length (tb->fields) >= 1);
9439 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9441 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9442 mono_loader_unlock ();
9446 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9447 klass->element_class = mono_class_from_mono_type (enum_basetype);
9448 if (!klass->element_class)
9449 klass->element_class = mono_class_from_mono_type (enum_basetype);
9452 * get the element_class from the current corlib.
9454 ec = default_class_from_mono_type (enum_basetype);
9455 klass->instance_size = ec->instance_size;
9456 klass->size_inited = 1;
9458 * this is almost safe to do with enums and it's needed to be able
9459 * to create objects of the enum type (for use in SetConstant).
9461 /* FIXME: Does this mean enums can't have method overrides ? */
9462 mono_class_setup_vtable_general (klass, NULL, 0);
9464 mono_loader_unlock ();
9467 static MonoMarshalSpec*
9468 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9469 MonoReflectionMarshal *minfo)
9471 MonoMarshalSpec *res;
9473 res = image_g_new0 (image, MonoMarshalSpec, 1);
9474 res->native = minfo->type;
9476 switch (minfo->type) {
9477 case MONO_NATIVE_LPARRAY:
9478 res->data.array_data.elem_type = minfo->eltype;
9479 if (minfo->has_size) {
9480 res->data.array_data.param_num = minfo->param_num;
9481 res->data.array_data.num_elem = minfo->count;
9482 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9485 res->data.array_data.param_num = -1;
9486 res->data.array_data.num_elem = -1;
9487 res->data.array_data.elem_mult = -1;
9491 case MONO_NATIVE_BYVALTSTR:
9492 case MONO_NATIVE_BYVALARRAY:
9493 res->data.array_data.num_elem = minfo->count;
9496 case MONO_NATIVE_CUSTOM:
9497 if (minfo->marshaltyperef)
9498 res->data.custom_data.custom_name =
9499 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9501 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9510 #endif /* !DISABLE_REFLECTION_EMIT */
9512 MonoReflectionMarshal*
9513 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9514 MonoMarshalSpec *spec)
9516 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9517 MonoReflectionMarshal *minfo;
9520 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9521 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9522 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9523 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9526 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9527 minfo->type = spec->native;
9529 switch (minfo->type) {
9530 case MONO_NATIVE_LPARRAY:
9531 minfo->eltype = spec->data.array_data.elem_type;
9532 minfo->count = spec->data.array_data.num_elem;
9533 minfo->param_num = spec->data.array_data.param_num;
9536 case MONO_NATIVE_BYVALTSTR:
9537 case MONO_NATIVE_BYVALARRAY:
9538 minfo->count = spec->data.array_data.num_elem;
9541 case MONO_NATIVE_CUSTOM:
9542 if (spec->data.custom_data.custom_name) {
9543 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9545 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9547 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9549 if (spec->data.custom_data.cookie)
9550 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9560 #ifndef DISABLE_REFLECTION_EMIT
9562 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9563 ReflectionMethodBuilder *rmb,
9564 MonoMethodSignature *sig)
9567 MonoMethodNormal *pm;
9568 MonoMarshalSpec **specs;
9569 MonoReflectionMethodAux *method_aux;
9575 * Methods created using a MethodBuilder should have their memory allocated
9576 * inside the image mempool, while dynamic methods should have their memory
9579 dynamic = rmb->refs != NULL;
9580 image = dynamic ? NULL : klass->image;
9583 g_assert (!klass->generic_class);
9585 mono_loader_lock ();
9587 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9588 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9589 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9591 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9593 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9595 pm = (MonoMethodNormal*)m;
9597 m->dynamic = dynamic;
9599 m->flags = rmb->attrs;
9600 m->iflags = rmb->iattrs;
9601 m->name = mono_string_to_utf8_image (image, rmb->name);
9604 m->skip_visibility = rmb->skip_visibility;
9606 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9608 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9609 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9612 m->signature->pinvoke = 1;
9613 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9614 m->signature->pinvoke = 1;
9616 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9618 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9619 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9621 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9623 if (klass->image->dynamic)
9624 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9626 mono_loader_unlock ();
9629 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9630 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9631 MonoMethodHeader *header;
9633 gint32 max_stack, i;
9634 gint32 num_locals = 0;
9635 gint32 num_clauses = 0;
9639 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9640 code_size = rmb->ilgen->code_len;
9641 max_stack = rmb->ilgen->max_stack;
9642 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9643 if (rmb->ilgen->ex_handlers)
9644 num_clauses = method_count_clauses (rmb->ilgen);
9647 code = mono_array_addr (rmb->code, guint8, 0);
9648 code_size = mono_array_length (rmb->code);
9649 /* we probably need to run a verifier on the code... */
9659 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9660 header->code_size = code_size;
9661 header->code = image_g_malloc (image, code_size);
9662 memcpy ((char*)header->code, code, code_size);
9663 header->max_stack = max_stack;
9664 header->init_locals = rmb->init_locals;
9665 header->num_locals = num_locals;
9667 for (i = 0; i < num_locals; ++i) {
9668 MonoReflectionLocalBuilder *lb =
9669 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9671 header->locals [i] = image_g_new0 (image, MonoType, 1);
9672 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9675 header->num_clauses = num_clauses;
9677 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9678 rmb->ilgen, num_clauses);
9681 pm->header = header;
9684 if (rmb->generic_params) {
9685 int count = mono_array_length (rmb->generic_params);
9686 MonoGenericContainer *container;
9688 container = rmb->generic_container;
9690 m->is_generic = TRUE;
9691 mono_method_set_generic_container (m, container);
9693 container->type_argc = count;
9694 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9695 container->owner.method = m;
9697 for (i = 0; i < count; i++) {
9698 MonoReflectionGenericParam *gp =
9699 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9700 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9701 container->type_params [i] = *param;
9704 if (klass->generic_container) {
9705 container->parent = klass->generic_container;
9706 container->context.class_inst = klass->generic_container->context.class_inst;
9708 container->context.method_inst = mono_get_shared_generic_inst (container);
9712 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9716 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9718 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9719 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9720 for (i = 0; i < rmb->nrefs; ++i)
9721 data [i + 1] = rmb->refs [i];
9726 /* Parameter info */
9729 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9730 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9731 for (i = 0; i <= m->signature->param_count; ++i) {
9732 MonoReflectionParamBuilder *pb;
9733 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9734 if ((i > 0) && (pb->attrs)) {
9735 /* Make a copy since it might point to a shared type structure */
9736 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9737 m->signature->params [i - 1]->attrs = pb->attrs;
9740 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9741 MonoDynamicImage *assembly;
9742 guint32 idx, def_type, len;
9746 if (!method_aux->param_defaults) {
9747 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9748 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9750 assembly = (MonoDynamicImage*)klass->image;
9751 idx = encode_constant (assembly, pb->def_value, &def_type);
9752 /* Copy the data from the blob since it might get realloc-ed */
9753 p = assembly->blob.data + idx;
9754 len = mono_metadata_decode_blob_size (p, &p2);
9756 method_aux->param_defaults [i] = image_g_malloc (image, len);
9757 method_aux->param_default_types [i] = def_type;
9758 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9762 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9764 if (!method_aux->param_cattr)
9765 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9766 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9772 /* Parameter marshalling */
9775 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9776 MonoReflectionParamBuilder *pb;
9777 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9778 if (pb->marshal_info) {
9780 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9781 specs [pb->position] =
9782 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9786 if (specs != NULL) {
9788 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9789 method_aux->param_marshall = specs;
9792 if (klass->image->dynamic && method_aux)
9793 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9795 mono_loader_unlock ();
9801 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9803 ReflectionMethodBuilder rmb;
9804 MonoMethodSignature *sig;
9806 mono_loader_lock ();
9807 sig = ctor_builder_to_signature (klass->image, mb);
9808 mono_loader_unlock ();
9810 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9812 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9813 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9815 /* If we are in a generic class, we might be called multiple times from inflate_method */
9816 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9817 /* ilgen is no longer needed */
9825 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9827 ReflectionMethodBuilder rmb;
9828 MonoMethodSignature *sig;
9830 mono_loader_lock ();
9831 sig = method_builder_to_signature (klass->image, mb);
9832 mono_loader_unlock ();
9834 reflection_methodbuilder_from_method_builder (&rmb, mb);
9836 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9837 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9839 /* If we are in a generic class, we might be called multiple times from inflate_method */
9840 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9841 /* ilgen is no longer needed */
9847 static MonoClassField*
9848 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9850 MonoClassField *field;
9853 field = g_new0 (MonoClassField, 1);
9855 field->name = mono_string_to_utf8 (fb->name);
9856 if (fb->attrs || fb->modreq || fb->modopt) {
9857 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9858 field->type->attrs = fb->attrs;
9860 g_assert (klass->image->dynamic);
9861 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9862 g_free (field->type);
9863 field->type = custom;
9865 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9867 if (fb->offset != -1)
9868 field->offset = fb->offset;
9869 field->parent = klass;
9870 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9872 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9879 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9882 MonoReflectionTypeBuilder *tb = NULL;
9883 gboolean is_dynamic = FALSE;
9887 mono_loader_lock ();
9889 domain = mono_object_domain (type);
9891 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9892 tb = (MonoReflectionTypeBuilder *) type;
9895 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9896 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9898 tb = rgi->generic_type;
9902 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9903 if (tb && tb->generic_container)
9904 mono_reflection_create_generic_class (tb);
9906 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9907 if (!klass->generic_container) {
9908 mono_loader_unlock ();
9912 if (klass->wastypebuilder) {
9913 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9918 mono_loader_unlock ();
9920 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9922 return &geninst->byval_arg;
9926 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9928 MonoGenericClass *gclass;
9929 MonoGenericInst *inst;
9931 g_assert (klass->generic_container);
9933 inst = mono_metadata_get_generic_inst (type_argc, types);
9934 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9936 return mono_generic_class_get_class (gclass);
9939 MonoReflectionMethod*
9940 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9943 MonoMethod *method, *inflated;
9944 MonoMethodInflated *imethod;
9945 MonoGenericContext tmp_context;
9946 MonoGenericInst *ginst;
9947 MonoType **type_argv;
9950 MONO_ARCH_SAVE_REGS;
9952 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9953 #ifndef DISABLE_REFLECTION_EMIT
9954 MonoReflectionMethodBuilder *mb = NULL;
9955 MonoReflectionTypeBuilder *tb;
9958 mb = (MonoReflectionMethodBuilder *) rmethod;
9959 tb = (MonoReflectionTypeBuilder *) mb->type;
9960 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
9962 method = methodbuilder_to_mono_method (klass, mb);
9964 g_assert_not_reached ();
9968 method = rmethod->method;
9971 klass = method->klass;
9973 if (method->is_inflated)
9974 method = ((MonoMethodInflated *) method)->declaring;
9976 count = mono_method_signature (method)->generic_param_count;
9977 if (count != mono_array_length (types))
9980 type_argv = g_new0 (MonoType *, count);
9981 for (i = 0; i < count; i++) {
9982 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9983 type_argv [i] = mono_reflection_type_get_handle (garg);
9985 ginst = mono_metadata_get_generic_inst (count, type_argv);
9988 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9989 tmp_context.method_inst = ginst;
9991 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9992 imethod = (MonoMethodInflated *) inflated;
9994 if (method->klass->image->dynamic) {
9995 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9997 * This table maps metadata structures representing inflated methods/fields
9998 * to the reflection objects representing their generic definitions.
10000 mono_loader_lock ();
10001 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10002 mono_loader_unlock ();
10005 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10008 #ifndef DISABLE_REFLECTION_EMIT
10010 static MonoMethod *
10011 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10013 MonoMethodInflated *imethod;
10014 MonoGenericContext *context;
10018 * With generic code sharing the klass might not be inflated.
10019 * This can happen because classes inflated with their own
10020 * type arguments are "normalized" to the uninflated class.
10022 if (!klass->generic_class)
10025 context = mono_class_get_context (klass);
10027 if (klass->method.count) {
10028 /* Find the already created inflated method */
10029 for (i = 0; i < klass->method.count; ++i) {
10030 g_assert (klass->methods [i]->is_inflated);
10031 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10034 g_assert (i < klass->method.count);
10035 imethod = (MonoMethodInflated*)klass->methods [i];
10037 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10040 if (method->is_generic && method->klass->image->dynamic) {
10041 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10043 mono_loader_lock ();
10044 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10045 mono_loader_unlock ();
10047 return (MonoMethod *) imethod;
10050 static MonoMethod *
10051 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
10053 MonoMethod *method;
10056 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
10058 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10059 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10060 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10062 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10063 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10064 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10065 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10066 method = ((MonoReflectionMethod *) obj)->method;
10068 method = NULL; /* prevent compiler warning */
10069 g_error ("can't handle type %s", obj->vtable->klass->name);
10072 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10075 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10077 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10078 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10081 MonoGenericClass *gclass;
10082 MonoDynamicGenericClass *dgclass;
10083 MonoClass *klass, *gklass;
10087 MONO_ARCH_SAVE_REGS;
10089 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10090 klass = mono_class_from_mono_type (gtype);
10091 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10092 gclass = gtype->data.generic_class;
10094 g_assert (gclass->is_dynamic);
10095 dgclass = (MonoDynamicGenericClass *) gclass;
10097 if (dgclass->initialized)
10100 gklass = gclass->container_class;
10101 mono_class_init (gklass);
10103 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10104 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10105 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10106 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10107 dgclass->count_events = events ? mono_array_length (events) : 0;
10109 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10110 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10111 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10112 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10113 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10114 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10115 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10117 for (i = 0; i < dgclass->count_methods; i++) {
10118 MonoObject *obj = mono_array_get (methods, gpointer, i);
10120 dgclass->methods [i] = inflate_method (type, obj);
10123 for (i = 0; i < dgclass->count_ctors; i++) {
10124 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10126 dgclass->ctors [i] = inflate_method (type, obj);
10129 for (i = 0; i < dgclass->count_fields; i++) {
10130 MonoObject *obj = mono_array_get (fields, gpointer, i);
10131 MonoClassField *field, *inflated_field = NULL;
10133 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10134 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10135 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10136 field = ((MonoReflectionField *) obj)->field;
10138 field = NULL; /* prevent compiler warning */
10139 g_assert_not_reached ();
10142 dgclass->fields [i] = *field;
10143 dgclass->fields [i].parent = klass;
10144 dgclass->fields [i].type = mono_class_inflate_generic_type (
10145 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10146 dgclass->field_generic_types [i] = field->type;
10147 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10148 dgclass->field_objects [i] = obj;
10150 if (inflated_field) {
10151 g_free (inflated_field);
10153 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10157 for (i = 0; i < dgclass->count_properties; i++) {
10158 MonoObject *obj = mono_array_get (properties, gpointer, i);
10159 MonoProperty *property = &dgclass->properties [i];
10161 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10162 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10164 property->parent = klass;
10165 property->attrs = pb->attrs;
10166 property->name = mono_string_to_utf8 (pb->name);
10167 if (pb->get_method)
10168 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10169 if (pb->set_method)
10170 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10171 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10172 *property = *((MonoReflectionProperty *) obj)->property;
10173 property->name = g_strdup (property->name);
10176 property->get = inflate_mono_method (klass, property->get, NULL);
10178 property->set = inflate_mono_method (klass, property->set, NULL);
10180 g_assert_not_reached ();
10183 for (i = 0; i < dgclass->count_events; i++) {
10184 MonoObject *obj = mono_array_get (events, gpointer, i);
10185 MonoEvent *event = &dgclass->events [i];
10187 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10188 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10190 event->parent = klass;
10191 event->attrs = eb->attrs;
10192 event->name = mono_string_to_utf8 (eb->name);
10193 if (eb->add_method)
10194 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10195 if (eb->remove_method)
10196 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10197 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10198 *event = *((MonoReflectionMonoEvent *) obj)->event;
10199 event->name = g_strdup (event->name);
10202 event->add = inflate_mono_method (klass, event->add, NULL);
10204 event->remove = inflate_mono_method (klass, event->remove, NULL);
10206 g_assert_not_reached ();
10209 dgclass->initialized = TRUE;
10213 ensure_generic_class_runtime_vtable (MonoClass *klass)
10215 MonoClass *gklass = klass->generic_class->container_class;
10218 if (klass->wastypebuilder)
10221 ensure_runtime_vtable (gklass);
10223 klass->method.count = gklass->method.count;
10224 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10226 for (i = 0; i < klass->method.count; i++) {
10227 klass->methods [i] = mono_class_inflate_generic_method_full (
10228 gklass->methods [i], klass, mono_class_get_context (klass));
10231 klass->interface_count = gklass->interface_count;
10232 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10233 for (i = 0; i < klass->interface_count; ++i) {
10234 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10235 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10236 mono_metadata_free_type (iface_type);
10238 ensure_runtime_vtable (klass->interfaces [i]);
10240 klass->interfaces_inited = 1;
10242 /*We can only finish with this klass once it's parent has as well*/
10243 if (gklass->wastypebuilder)
10244 klass->wastypebuilder = TRUE;
10249 ensure_runtime_vtable (MonoClass *klass)
10251 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10254 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10257 ensure_runtime_vtable (klass->parent);
10260 num = tb->ctors? mono_array_length (tb->ctors): 0;
10261 num += tb->num_methods;
10262 klass->method.count = num;
10263 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10264 num = tb->ctors? mono_array_length (tb->ctors): 0;
10265 for (i = 0; i < num; ++i)
10266 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10267 num = tb->num_methods;
10269 for (i = 0; i < num; ++i)
10270 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10272 if (tb->interfaces) {
10273 klass->interface_count = mono_array_length (tb->interfaces);
10274 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10275 for (i = 0; i < klass->interface_count; ++i) {
10276 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10277 klass->interfaces [i] = mono_class_from_mono_type (iface);
10278 ensure_runtime_vtable (klass->interfaces [i]);
10280 klass->interfaces_inited = 1;
10282 } else if (klass->generic_class){
10283 ensure_generic_class_runtime_vtable (klass);
10286 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10287 for (i = 0; i < klass->method.count; ++i)
10288 klass->methods [i]->slot = i;
10290 mono_class_setup_interface_offsets (klass);
10291 mono_class_setup_interface_id (klass);
10295 * The generic vtable is needed even if image->run is not set since some
10296 * runtime code like ves_icall_Type_GetMethodsByName depends on
10297 * method->slot being defined.
10301 * tb->methods could not be freed since it is used for determining
10302 * overrides during dynamic vtable construction.
10307 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10309 MonoReflectionTypeBuilder *tb;
10313 *num_overrides = 0;
10315 g_assert (klass->image->dynamic);
10317 if (!klass->reflection_info)
10320 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10322 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10326 for (i = 0; i < tb->num_methods; ++i) {
10327 MonoReflectionMethodBuilder *mb =
10328 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10329 if (mb->override_method)
10335 *overrides = g_new0 (MonoMethod*, onum * 2);
10338 for (i = 0; i < tb->num_methods; ++i) {
10339 MonoReflectionMethodBuilder *mb =
10340 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10341 if (mb->override_method) {
10342 (*overrides) [onum * 2] =
10343 mb->override_method->method;
10344 (*overrides) [onum * 2 + 1] =
10347 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10348 g_assert (mb->override_method->method);
10349 g_assert (mb->mhandle);
10356 *num_overrides = onum;
10360 typebuilder_setup_fields (MonoClass *klass)
10362 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10363 MonoReflectionFieldBuilder *fb;
10364 MonoClassField *field;
10365 MonoImage *image = klass->image;
10366 const char *p, *p2;
10368 guint32 len, idx, real_size = 0;
10370 klass->field.count = tb->num_fields;
10371 klass->field.first = 0;
10373 if (tb->class_size) {
10374 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10375 klass->packing_size = tb->packing_size;
10376 real_size = klass->instance_size + tb->class_size;
10379 if (!klass->field.count) {
10380 klass->instance_size = MAX (klass->instance_size, real_size);
10384 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10385 mono_class_alloc_ext (klass);
10386 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10388 for (i = 0; i < klass->field.count; ++i) {
10389 fb = mono_array_get (tb->fields, gpointer, i);
10390 field = &klass->fields [i];
10391 field->name = mono_string_to_utf8_image (image, fb->name);
10393 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10394 field->type->attrs = fb->attrs;
10396 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10398 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10399 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10400 if (fb->offset != -1)
10401 field->offset = fb->offset;
10402 field->parent = klass;
10403 fb->handle = field;
10404 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10406 if (fb->def_value) {
10407 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10408 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10409 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10410 /* Copy the data from the blob since it might get realloc-ed */
10411 p = assembly->blob.data + idx;
10412 len = mono_metadata_decode_blob_size (p, &p2);
10414 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10415 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10419 klass->instance_size = MAX (klass->instance_size, real_size);
10420 mono_class_layout_fields (klass);
10424 typebuilder_setup_properties (MonoClass *klass)
10426 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10427 MonoReflectionPropertyBuilder *pb;
10428 MonoImage *image = klass->image;
10429 MonoProperty *properties;
10433 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10435 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10436 klass->ext->property.first = 0;
10438 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10439 klass->ext->properties = properties;
10440 for (i = 0; i < klass->ext->property.count; ++i) {
10441 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10442 properties [i].parent = klass;
10443 properties [i].attrs = pb->attrs;
10444 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10445 if (pb->get_method)
10446 properties [i].get = pb->get_method->mhandle;
10447 if (pb->set_method)
10448 properties [i].set = pb->set_method->mhandle;
10450 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10454 MonoReflectionEvent *
10455 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10457 MonoEvent *event = g_new0 (MonoEvent, 1);
10461 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10463 event->parent = klass;
10464 event->attrs = eb->attrs;
10465 event->name = mono_string_to_utf8 (eb->name);
10466 if (eb->add_method)
10467 event->add = eb->add_method->mhandle;
10468 if (eb->remove_method)
10469 event->remove = eb->remove_method->mhandle;
10470 if (eb->raise_method)
10471 event->raise = eb->raise_method->mhandle;
10473 if (eb->other_methods) {
10474 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10475 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10476 MonoReflectionMethodBuilder *mb =
10477 mono_array_get (eb->other_methods,
10478 MonoReflectionMethodBuilder*, j);
10479 event->other [j] = mb->mhandle;
10483 return mono_event_get_object (mono_object_domain (tb), klass, event);
10487 typebuilder_setup_events (MonoClass *klass)
10489 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10490 MonoReflectionEventBuilder *eb;
10491 MonoImage *image = klass->image;
10496 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10498 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10499 klass->ext->event.first = 0;
10501 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10502 klass->ext->events = events;
10503 for (i = 0; i < klass->ext->event.count; ++i) {
10504 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10505 events [i].parent = klass;
10506 events [i].attrs = eb->attrs;
10507 events [i].name = mono_string_to_utf8_image (image, eb->name);
10508 if (eb->add_method)
10509 events [i].add = eb->add_method->mhandle;
10510 if (eb->remove_method)
10511 events [i].remove = eb->remove_method->mhandle;
10512 if (eb->raise_method)
10513 events [i].raise = eb->raise_method->mhandle;
10515 if (eb->other_methods) {
10516 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10517 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10518 MonoReflectionMethodBuilder *mb =
10519 mono_array_get (eb->other_methods,
10520 MonoReflectionMethodBuilder*, j);
10521 events [i].other [j] = mb->mhandle;
10524 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10529 remove_instantiations_of (gpointer key,
10531 gpointer user_data)
10533 MonoType *type = (MonoType*)key;
10534 MonoClass *klass = (MonoClass*)user_data;
10536 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10543 check_array_for_usertypes (MonoArray *arr)
10550 for (i = 0; i < mono_array_length (arr); ++i)
10551 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10554 MonoReflectionType*
10555 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10558 MonoDomain* domain;
10559 MonoReflectionType* res;
10562 MONO_ARCH_SAVE_REGS;
10564 domain = mono_object_domain (tb);
10565 klass = mono_class_from_mono_type (tb->type.type);
10568 * Check for user defined Type subclasses.
10570 RESOLVE_TYPE (tb->parent);
10571 check_array_for_usertypes (tb->interfaces);
10573 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10574 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10576 RESOLVE_TYPE (fb->type);
10577 check_array_for_usertypes (fb->modreq);
10578 check_array_for_usertypes (fb->modopt);
10579 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10580 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10585 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10586 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10588 RESOLVE_TYPE (mb->rtype);
10589 check_array_for_usertypes (mb->return_modreq);
10590 check_array_for_usertypes (mb->return_modopt);
10591 check_array_for_usertypes (mb->parameters);
10592 if (mb->param_modreq)
10593 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10594 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10595 if (mb->param_modopt)
10596 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10597 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10602 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10603 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10605 check_array_for_usertypes (mb->parameters);
10606 if (mb->param_modreq)
10607 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10608 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10609 if (mb->param_modopt)
10610 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10611 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10616 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10619 * we need to lock the domain because the lock will be taken inside
10620 * So, we need to keep the locking order correct.
10622 mono_loader_lock ();
10623 mono_domain_lock (domain);
10624 if (klass->wastypebuilder) {
10625 mono_domain_unlock (domain);
10626 mono_loader_unlock ();
10627 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10630 * Fields to set in klass:
10631 * the various flags: delegate/unicode/contextbound etc.
10633 klass->flags = tb->attrs;
10634 klass->has_cctor = 1;
10635 klass->has_finalize = 1;
10638 if (!((MonoDynamicImage*)klass->image)->run) {
10639 if (klass->generic_container) {
10640 /* FIXME: The code below can't handle generic classes */
10641 klass->wastypebuilder = TRUE;
10642 mono_loader_unlock ();
10643 mono_domain_unlock (domain);
10644 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10649 /* enums are done right away */
10650 if (!klass->enumtype)
10651 ensure_runtime_vtable (klass);
10653 if (tb->subtypes) {
10654 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10655 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10656 mono_class_alloc_ext (klass);
10657 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)));
10661 klass->nested_classes_inited = TRUE;
10663 /* fields and object layout */
10664 if (klass->parent) {
10665 if (!klass->parent->size_inited)
10666 mono_class_init (klass->parent);
10667 klass->instance_size = klass->parent->instance_size;
10668 klass->sizes.class_size = 0;
10669 klass->min_align = klass->parent->min_align;
10670 /* if the type has no fields we won't call the field_setup
10671 * routine which sets up klass->has_references.
10673 klass->has_references |= klass->parent->has_references;
10675 klass->instance_size = sizeof (MonoObject);
10676 klass->min_align = 1;
10679 /* FIXME: handle packing_size and instance_size */
10680 typebuilder_setup_fields (klass);
10682 typebuilder_setup_properties (klass);
10684 typebuilder_setup_events (klass);
10686 klass->wastypebuilder = TRUE;
10689 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10690 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10691 * we want to return normal System.MonoType objects, so clear these out from the cache.
10693 if (domain->type_hash && klass->generic_container)
10694 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10696 mono_domain_unlock (domain);
10697 mono_loader_unlock ();
10699 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10700 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10701 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10704 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10705 g_assert (res != (MonoReflectionType*)tb);
10711 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10713 MonoGenericParamFull *param;
10717 MONO_ARCH_SAVE_REGS;
10719 param = g_new0 (MonoGenericParamFull, 1);
10721 if (gparam->mbuilder) {
10722 if (!gparam->mbuilder->generic_container) {
10723 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10724 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10725 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10726 gparam->mbuilder->generic_container->is_method = TRUE;
10728 * Cannot set owner.method, since the MonoMethod is not created yet.
10729 * Set the image field instead, so type_in_image () works.
10731 gparam->mbuilder->generic_container->image = klass->image;
10733 param->param.owner = gparam->mbuilder->generic_container;
10734 } else if (gparam->tbuilder) {
10735 if (!gparam->tbuilder->generic_container) {
10736 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10737 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10738 gparam->tbuilder->generic_container->owner.klass = klass;
10740 param->param.owner = gparam->tbuilder->generic_container;
10743 param->info.name = mono_string_to_utf8 (gparam->name);
10744 param->param.num = gparam->index;
10746 image = &gparam->tbuilder->module->dynamic_image->image;
10747 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10749 gparam->type.type = &pklass->byval_arg;
10751 MOVING_GC_REGISTER (&pklass->reflection_info);
10752 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10753 mono_image_lock (image);
10754 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10755 mono_image_unlock (image);
10759 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10761 MonoReflectionModuleBuilder *module = sig->module;
10762 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10763 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10768 check_array_for_usertypes (sig->arguments);
10770 sigbuffer_init (&buf, 32);
10772 sigbuffer_add_value (&buf, 0x07);
10773 sigbuffer_add_value (&buf, na);
10774 if (assembly != NULL){
10775 for (i = 0; i < na; ++i) {
10776 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10777 encode_reflection_type (assembly, type, &buf);
10781 buflen = buf.p - buf.buf;
10782 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10783 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10784 sigbuffer_free (&buf);
10790 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10792 MonoDynamicImage *assembly = sig->module->dynamic_image;
10793 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10798 check_array_for_usertypes (sig->arguments);
10800 sigbuffer_init (&buf, 32);
10802 sigbuffer_add_value (&buf, 0x06);
10803 for (i = 0; i < na; ++i) {
10804 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10805 encode_reflection_type (assembly, type, &buf);
10808 buflen = buf.p - buf.buf;
10809 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10810 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10811 sigbuffer_free (&buf);
10817 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10819 ReflectionMethodBuilder rmb;
10820 MonoMethodSignature *sig;
10825 sig = dynamic_method_to_signature (mb);
10827 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10830 * Resolve references.
10833 * Every second entry in the refs array is reserved for storing handle_class,
10834 * which is needed by the ldtoken implementation in the JIT.
10836 rmb.nrefs = mb->nrefs;
10837 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10838 for (i = 0; i < mb->nrefs; i += 2) {
10839 MonoClass *handle_class;
10841 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10843 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10844 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10846 * The referenced DynamicMethod should already be created by the managed
10847 * code, except in the case of circular references. In that case, we store
10848 * method in the refs array, and fix it up later when the referenced
10849 * DynamicMethod is created.
10851 if (method->mhandle) {
10852 ref = method->mhandle;
10854 /* FIXME: GC object stored in unmanaged memory */
10857 /* FIXME: GC object stored in unmanaged memory */
10858 method->referenced_by = g_slist_append (method->referenced_by, mb);
10860 handle_class = mono_defaults.methodhandle_class;
10862 MonoException *ex = NULL;
10863 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10865 ex = mono_get_exception_type_load (NULL, NULL);
10866 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10867 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10871 mono_raise_exception (ex);
10876 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10877 rmb.refs [i + 1] = handle_class;
10880 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10882 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10884 /* Fix up refs entries pointing at us */
10885 for (l = mb->referenced_by; l; l = l->next) {
10886 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10887 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10890 g_assert (method->mhandle);
10892 data = (gpointer*)wrapper->method_data;
10893 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10894 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10895 data [i + 1] = mb->mhandle;
10898 g_slist_free (mb->referenced_by);
10902 /* ilgen is no longer needed */
10906 #endif /* DISABLE_REFLECTION_EMIT */
10909 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10914 mono_runtime_free_method (
10915 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10920 * mono_reflection_is_valid_dynamic_token:
10922 * Returns TRUE if token is valid.
10926 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10928 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10931 #ifndef DISABLE_REFLECTION_EMIT
10934 * mono_reflection_lookup_dynamic_token:
10936 * Finish the Builder object pointed to by TOKEN and return the corresponding
10937 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10938 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10941 * LOCKING: Take the loader lock
10944 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10946 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10950 mono_loader_lock ();
10951 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10952 mono_loader_unlock ();
10955 g_error ("Could not find required dynamic token 0x%08x", token);
10961 handle_class = &klass;
10962 return resolve_object (image, obj, handle_class, context);
10966 * ensure_complete_type:
10968 * Ensure that KLASS is completed if it is a dynamic type, or references
10972 ensure_complete_type (MonoClass *klass)
10974 if (klass->image->dynamic && !klass->wastypebuilder) {
10975 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10977 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10979 // Asserting here could break a lot of code
10980 //g_assert (klass->wastypebuilder);
10983 if (klass->generic_class) {
10984 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10987 for (i = 0; i < inst->type_argc; ++i) {
10988 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10994 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10996 gpointer result = NULL;
10998 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10999 result = mono_string_intern ((MonoString*)obj);
11000 *handle_class = mono_defaults.string_class;
11002 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11003 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11005 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11006 result = mono_class_from_mono_type (inflated);
11007 mono_metadata_free_type (inflated);
11009 result = mono_class_from_mono_type (type);
11011 *handle_class = mono_defaults.typehandle_class;
11013 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11014 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11015 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11016 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11017 result = ((MonoReflectionMethod*)obj)->method;
11019 result = mono_class_inflate_generic_method (result, context);
11020 *handle_class = mono_defaults.methodhandle_class;
11022 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11024 result = mb->mhandle;
11026 /* Type is not yet created */
11027 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11029 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11032 * Hopefully this has been filled in by calling CreateType() on the
11036 * TODO: This won't work if the application finishes another
11037 * TypeBuilder instance instead of this one.
11039 result = mb->mhandle;
11042 result = mono_class_inflate_generic_method (result, context);
11043 *handle_class = mono_defaults.methodhandle_class;
11044 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11045 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11047 result = cb->mhandle;
11049 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11051 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11052 result = cb->mhandle;
11055 result = mono_class_inflate_generic_method (result, context);
11056 *handle_class = mono_defaults.methodhandle_class;
11057 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11058 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11060 ensure_complete_type (field->parent);
11062 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11063 MonoClass *class = mono_class_from_mono_type (inflated);
11064 MonoClassField *inflated_field;
11065 gpointer iter = NULL;
11066 mono_metadata_free_type (inflated);
11067 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11068 if (!strcmp (field->name, inflated_field->name))
11071 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11072 result = inflated_field;
11076 *handle_class = mono_defaults.fieldhandle_class;
11078 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11079 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11080 result = fb->handle;
11083 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11085 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11086 result = fb->handle;
11089 if (fb->handle && fb->handle->parent->generic_container) {
11090 MonoClass *klass = fb->handle->parent;
11091 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11092 MonoClass *inflated = mono_class_from_mono_type (type);
11094 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11096 mono_metadata_free_type (type);
11098 *handle_class = mono_defaults.fieldhandle_class;
11099 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11100 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11101 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11104 klass = type->data.klass;
11105 if (klass->wastypebuilder) {
11106 /* Already created */
11110 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11111 result = type->data.klass;
11114 *handle_class = mono_defaults.typehandle_class;
11115 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11116 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11117 MonoMethodSignature *sig;
11120 if (helper->arguments)
11121 nargs = mono_array_length (helper->arguments);
11125 sig = mono_metadata_signature_alloc (image, nargs);
11126 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11127 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11129 if (helper->call_conv == 0) /* unmanaged */
11130 sig->call_convention = helper->unmanaged_call_conv - 1;
11132 if (helper->call_conv & 0x02)
11133 sig->call_convention = MONO_CALL_VARARG;
11135 sig->call_convention = MONO_CALL_DEFAULT;
11137 sig->param_count = nargs;
11138 /* TODO: Copy type ? */
11139 sig->ret = helper->return_type->type;
11140 for (i = 0; i < nargs; ++i)
11141 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11144 *handle_class = NULL;
11145 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11146 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11147 /* Already created by the managed code */
11148 g_assert (method->mhandle);
11149 result = method->mhandle;
11150 *handle_class = mono_defaults.methodhandle_class;
11151 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11152 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11153 type = mono_class_inflate_generic_type (type, context);
11154 result = mono_class_from_mono_type (type);
11155 *handle_class = mono_defaults.typehandle_class;
11157 mono_metadata_free_type (type);
11158 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11159 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11160 type = mono_class_inflate_generic_type (type, context);
11161 result = mono_class_from_mono_type (type);
11162 *handle_class = mono_defaults.typehandle_class;
11164 mono_metadata_free_type (type);
11165 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11166 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11167 MonoClass *inflated;
11170 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11171 inflated = mono_class_from_mono_type (type);
11173 g_assert (f->fb->handle);
11174 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11176 mono_metadata_free_type (type);
11177 *handle_class = mono_defaults.fieldhandle_class;
11178 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11179 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11180 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11181 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11182 g_assert (c->cb->mhandle);
11183 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11184 *handle_class = mono_defaults.methodhandle_class;
11185 mono_metadata_free_type (type);
11186 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11187 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11188 if (m->method_args) {
11189 result = mono_reflection_method_on_tb_inst_get_handle (m);
11191 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11192 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11193 g_assert (m->mb->mhandle);
11194 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11195 mono_metadata_free_type (type);
11197 *handle_class = mono_defaults.methodhandle_class;
11198 } else if (is_sre_array (mono_object_get_class(obj)) ||
11199 is_sre_byref (mono_object_get_class(obj)) ||
11200 is_sre_pointer (mono_object_get_class(obj))) {
11201 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11202 MonoType *type = mono_reflection_type_get_handle (ref_type);
11203 result = mono_class_from_mono_type (type);
11204 *handle_class = mono_defaults.typehandle_class;
11206 g_print ("%s\n", obj->vtable->klass->name);
11207 g_assert_not_reached ();
11212 #else /* DISABLE_REFLECTION_EMIT */
11215 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11217 g_assert_not_reached ();
11222 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11224 g_assert_not_reached ();
11228 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11230 g_assert_not_reached ();
11234 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11236 g_assert_not_reached ();
11240 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11242 g_assert_not_reached ();
11246 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11248 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11252 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11254 g_assert_not_reached ();
11258 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11260 g_assert_not_reached ();
11263 MonoReflectionModule *
11264 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11266 g_assert_not_reached ();
11271 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11273 g_assert_not_reached ();
11278 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11280 g_assert_not_reached ();
11285 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11286 gboolean create_methodspec, gboolean register_token)
11288 g_assert_not_reached ();
11293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11298 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11299 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11302 g_assert_not_reached ();
11306 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11309 *num_overrides = 0;
11312 MonoReflectionEvent *
11313 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11315 g_assert_not_reached ();
11319 MonoReflectionType*
11320 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11322 g_assert_not_reached ();
11327 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11329 g_assert_not_reached ();
11333 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11335 g_assert_not_reached ();
11340 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11342 g_assert_not_reached ();
11347 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11352 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11358 mono_reflection_type_get_handle (MonoReflectionType* ref)
11365 #endif /* DISABLE_REFLECTION_EMIT */
11367 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11368 const static guint32 declsec_flags_map[] = {
11369 0x00000000, /* empty */
11370 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11371 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11372 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11373 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11374 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11375 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11376 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11377 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11378 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11379 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11380 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11381 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11382 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11383 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11384 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11385 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11386 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11387 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11391 * Returns flags that includes all available security action associated to the handle.
11392 * @token: metadata token (either for a class or a method)
11393 * @image: image where resides the metadata.
11396 mono_declsec_get_flags (MonoImage *image, guint32 token)
11398 int index = mono_metadata_declsec_from_index (image, token);
11399 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11400 guint32 result = 0;
11404 /* HasSecurity can be present for other, not specially encoded, attributes,
11405 e.g. SuppressUnmanagedCodeSecurityAttribute */
11409 for (i = index; i < t->rows; i++) {
11410 guint32 cols [MONO_DECL_SECURITY_SIZE];
11412 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11413 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11416 action = cols [MONO_DECL_SECURITY_ACTION];
11417 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11418 result |= declsec_flags_map [action];
11420 g_assert_not_reached ();
11427 * Get the security actions (in the form of flags) associated with the specified method.
11429 * @method: The method for which we want the declarative security flags.
11430 * Return the declarative security flags for the method (only).
11432 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11433 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11436 mono_declsec_flags_from_method (MonoMethod *method)
11438 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11439 /* FIXME: No cache (for the moment) */
11440 guint32 idx = mono_method_get_index (method);
11441 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11442 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11443 return mono_declsec_get_flags (method->klass->image, idx);
11449 * Get the security actions (in the form of flags) associated with the specified class.
11451 * @klass: The class for which we want the declarative security flags.
11452 * Return the declarative security flags for the class.
11454 * Note: We cache the flags inside the MonoClass structure as this will get
11455 * called very often (at least for each method).
11458 mono_declsec_flags_from_class (MonoClass *klass)
11460 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11461 if (!klass->ext || !klass->ext->declsec_flags) {
11464 idx = mono_metadata_token_index (klass->type_token);
11465 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11466 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11467 mono_loader_lock ();
11468 mono_class_alloc_ext (klass);
11469 mono_loader_unlock ();
11470 /* we cache the flags on classes */
11471 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11473 return klass->ext->declsec_flags;
11479 * Get the security actions (in the form of flags) associated with the specified assembly.
11481 * @assembly: The assembly for which we want the declarative security flags.
11482 * Return the declarative security flags for the assembly.
11485 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11487 guint32 idx = 1; /* there is only one assembly */
11488 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11489 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11490 return mono_declsec_get_flags (assembly->image, idx);
11495 * Fill actions for the specific index (which may either be an encoded class token or
11496 * an encoded method token) from the metadata image.
11497 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11500 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11501 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11503 MonoBoolean result = FALSE;
11505 guint32 cols [MONO_DECL_SECURITY_SIZE];
11506 int index = mono_metadata_declsec_from_index (image, token);
11509 t = &image->tables [MONO_TABLE_DECLSECURITY];
11510 for (i = index; i < t->rows; i++) {
11511 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11513 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11516 /* if present only replace (class) permissions with method permissions */
11517 /* if empty accept either class or method permissions */
11518 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11519 if (!actions->demand.blob) {
11520 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11521 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11522 actions->demand.blob = (char*) (blob + 2);
11523 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11526 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11527 if (!actions->noncasdemand.blob) {
11528 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11529 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11530 actions->noncasdemand.blob = (char*) (blob + 2);
11531 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11534 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11535 if (!actions->demandchoice.blob) {
11536 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11537 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11538 actions->demandchoice.blob = (char*) (blob + 2);
11539 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11549 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11550 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11552 guint32 idx = mono_metadata_token_index (klass->type_token);
11553 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11554 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11555 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11559 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11560 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11562 guint32 idx = mono_method_get_index (method);
11563 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11564 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11565 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11569 * Collect all actions (that requires to generate code in mini) assigned for
11570 * the specified method.
11571 * Note: Don't use the content of actions if the function return FALSE.
11574 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11576 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11577 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11578 MonoBoolean result = FALSE;
11581 /* quick exit if no declarative security is present in the metadata */
11582 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11585 /* we want the original as the wrapper is "free" of the security informations */
11586 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11587 method = mono_marshal_method_from_wrapper (method);
11592 /* First we look for method-level attributes */
11593 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11594 mono_class_init (method->klass);
11595 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11597 result = mono_declsec_get_method_demands_params (method, demands,
11598 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11601 /* Here we use (or create) the class declarative cache to look for demands */
11602 flags = mono_declsec_flags_from_class (method->klass);
11603 if (flags & mask) {
11605 mono_class_init (method->klass);
11606 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11608 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11609 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11612 /* The boolean return value is used as a shortcut in case nothing needs to
11613 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11619 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11621 * Note: Don't use the content of actions if the function return FALSE.
11624 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11626 MonoBoolean result = FALSE;
11629 /* quick exit if no declarative security is present in the metadata */
11630 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11633 /* we want the original as the wrapper is "free" of the security informations */
11634 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11635 method = mono_marshal_method_from_wrapper (method);
11640 /* results are independant - zeroize both */
11641 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11642 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11644 /* First we look for method-level attributes */
11645 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11646 mono_class_init (method->klass);
11648 result = mono_declsec_get_method_demands_params (method, cmethod,
11649 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11652 /* Here we use (or create) the class declarative cache to look for demands */
11653 flags = mono_declsec_flags_from_class (method->klass);
11654 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11655 mono_class_init (method->klass);
11657 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11658 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11665 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11667 * @klass The inherited class - this is the class that provides the security check (attributes)
11669 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11671 * Note: Don't use the content of actions if the function return FALSE.
11674 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11676 MonoBoolean result = FALSE;
11679 /* quick exit if no declarative security is present in the metadata */
11680 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11683 /* Here we use (or create) the class declarative cache to look for demands */
11684 flags = mono_declsec_flags_from_class (klass);
11685 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11686 mono_class_init (klass);
11687 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11689 result |= mono_declsec_get_class_demands_params (klass, demands,
11690 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11697 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11699 * Note: Don't use the content of actions if the function return FALSE.
11702 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11704 /* quick exit if no declarative security is present in the metadata */
11705 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11708 /* we want the original as the wrapper is "free" of the security informations */
11709 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11710 method = mono_marshal_method_from_wrapper (method);
11715 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11716 mono_class_init (method->klass);
11717 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11719 return mono_declsec_get_method_demands_params (method, demands,
11720 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11727 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11729 guint32 cols [MONO_DECL_SECURITY_SIZE];
11733 int index = mono_metadata_declsec_from_index (image, token);
11737 t = &image->tables [MONO_TABLE_DECLSECURITY];
11738 for (i = index; i < t->rows; i++) {
11739 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11741 /* shortcut - index are ordered */
11742 if (token != cols [MONO_DECL_SECURITY_PARENT])
11745 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11746 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11747 entry->blob = (char*) (metadata + 2);
11748 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11757 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11759 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11760 guint32 idx = mono_method_get_index (method);
11761 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11762 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11763 return get_declsec_action (method->klass->image, idx, action, entry);
11769 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11772 guint32 flags = mono_declsec_flags_from_class (klass);
11773 if (declsec_flags_map [action] & flags) {
11774 guint32 idx = mono_metadata_token_index (klass->type_token);
11775 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11776 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11777 return get_declsec_action (klass->image, idx, action, entry);
11783 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11785 guint32 idx = 1; /* there is only one assembly */
11786 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11787 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11789 return get_declsec_action (assembly->image, idx, action, entry);
11793 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11795 MonoObject *res, *exc;
11797 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11798 static MonoMethod *method = NULL;
11800 if (!System_Reflection_Emit_TypeBuilder) {
11801 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11802 g_assert (System_Reflection_Emit_TypeBuilder);
11804 if (method == NULL) {
11805 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11810 * The result of mono_type_get_object () might be a System.MonoType but we
11811 * need a TypeBuilder so use klass->reflection_info.
11813 g_assert (klass->reflection_info);
11814 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11816 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11818 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11822 return *(MonoBoolean*)mono_object_unbox (res);