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>
42 #include <mono/utils/mono-error-internals.h>
46 static void* reflection_info_desc = NULL;
47 #define MOVING_GC_REGISTER(addr) do { \
48 if (!reflection_info_desc) { \
50 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
52 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55 #define MOVING_GC_REGISTER(addr)
64 #define TEXT_OFFSET 512
65 #define CLI_H_SIZE 136
66 #define FILE_ALIGN 512
67 #define VIRT_ALIGN 8192
68 #define START_TEXT_RVA 0x00002000
71 MonoReflectionILGen *ilgen;
72 MonoReflectionType *rtype;
73 MonoArray *parameters;
74 MonoArray *generic_params;
75 MonoGenericContainer *generic_container;
81 guint32 *table_idx; /* note: it's a pointer */
85 MonoBoolean init_locals;
86 MonoBoolean skip_visibility;
87 MonoArray *return_modreq;
88 MonoArray *return_modopt;
89 MonoArray *param_modreq;
90 MonoArray *param_modopt;
91 MonoArray *permissions;
96 int charset, extra_flags, native_cc;
97 MonoString *dll, *dllentry;
98 } ReflectionMethodBuilder;
102 MonoReflectionGenericParam *gparam;
103 } GenericParamTableEntry;
105 const unsigned char table_sizes [MONO_TABLE_NUM] = {
115 MONO_INTERFACEIMPL_SIZE,
116 MONO_MEMBERREF_SIZE, /* 0x0A */
118 MONO_CUSTOM_ATTR_SIZE,
119 MONO_FIELD_MARSHAL_SIZE,
120 MONO_DECL_SECURITY_SIZE,
121 MONO_CLASS_LAYOUT_SIZE,
122 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
123 MONO_STAND_ALONE_SIGNATURE_SIZE,
127 MONO_PROPERTY_MAP_SIZE,
130 MONO_METHOD_SEMA_SIZE,
131 MONO_METHODIMPL_SIZE,
132 MONO_MODULEREF_SIZE, /* 0x1A */
138 MONO_ASSEMBLY_SIZE, /* 0x20 */
139 MONO_ASSEMBLY_PROCESSOR_SIZE,
140 MONO_ASSEMBLYOS_SIZE,
141 MONO_ASSEMBLYREF_SIZE,
142 MONO_ASSEMBLYREFPROC_SIZE,
143 MONO_ASSEMBLYREFOS_SIZE,
147 MONO_NESTED_CLASS_SIZE,
149 MONO_GENERICPARAM_SIZE, /* 0x2A */
150 MONO_METHODSPEC_SIZE,
151 MONO_GENPARCONSTRAINT_SIZE
155 #ifndef DISABLE_REFLECTION_EMIT
156 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
157 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
158 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
159 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
160 static void ensure_runtime_vtable (MonoClass *klass);
161 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
162 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
163 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
164 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
167 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
168 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
169 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
170 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
171 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
172 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
173 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
174 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
175 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
176 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
177 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
178 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
179 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
180 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
181 static gboolean is_sre_array (MonoClass *class);
182 static gboolean is_sre_byref (MonoClass *class);
183 static gboolean is_sre_pointer (MonoClass *class);
184 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
185 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
186 static MonoMethod * inflate_method (MonoReflectionGenericClass *type, MonoObject *obj);
188 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
189 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
190 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
191 __type = mono_reflection_type_resolve_user_types (__type); \
192 mono_array_set (arr, MonoReflectionType*, index, __type); \
195 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
198 mono_reflection_init (void)
203 sigbuffer_init (SigBuffer *buf, int size)
205 buf->buf = g_malloc (size);
207 buf->end = buf->buf + size;
211 sigbuffer_make_room (SigBuffer *buf, int size)
213 if (buf->end - buf->p < size) {
214 int new_size = buf->end - buf->buf + size + 32;
215 char *p = g_realloc (buf->buf, new_size);
216 size = buf->p - buf->buf;
219 buf->end = buf->buf + new_size;
224 sigbuffer_add_value (SigBuffer *buf, guint32 val)
226 sigbuffer_make_room (buf, 6);
227 mono_metadata_encode_value (val, buf->p, &buf->p);
231 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
233 sigbuffer_make_room (buf, 1);
239 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
241 sigbuffer_make_room (buf, size);
242 memcpy (buf->p, p, size);
247 sigbuffer_free (SigBuffer *buf)
252 #ifndef DISABLE_REFLECTION_EMIT
256 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
260 image_g_malloc (MonoImage *image, guint size)
263 return mono_image_alloc (image, size);
265 return g_malloc (size);
267 #endif /* !DISABLE_REFLECTION_EMIT */
272 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
276 image_g_malloc0 (MonoImage *image, guint size)
279 return mono_image_alloc0 (image, size);
281 return g_malloc0 (size);
284 #ifndef DISABLE_REFLECTION_EMIT
286 image_strdup (MonoImage *image, const char *s)
289 return mono_image_strdup (image, s);
295 #define image_g_new(image,struct_type, n_structs) \
296 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
298 #define image_g_new0(image,struct_type, n_structs) \
299 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
303 alloc_table (MonoDynamicTable *table, guint nrows)
306 g_assert (table->columns);
307 if (nrows + 1 >= table->alloc_rows) {
308 while (nrows + 1 >= table->alloc_rows) {
309 if (table->alloc_rows == 0)
310 table->alloc_rows = 16;
312 table->alloc_rows *= 2;
315 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
320 make_room_in_stream (MonoDynamicStream *stream, int size)
322 if (size <= stream->alloc_size)
325 while (stream->alloc_size <= size) {
326 if (stream->alloc_size < 4096)
327 stream->alloc_size = 4096;
329 stream->alloc_size *= 2;
332 stream->data = g_realloc (stream->data, stream->alloc_size);
336 string_heap_insert (MonoDynamicStream *sh, const char *str)
340 gpointer oldkey, oldval;
342 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
343 return GPOINTER_TO_UINT (oldval);
345 len = strlen (str) + 1;
348 make_room_in_stream (sh, idx + len);
351 * We strdup the string even if we already copy them in sh->data
352 * so that the string pointers in the hash remain valid even if
353 * we need to realloc sh->data. We may want to avoid that later.
355 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
356 memcpy (sh->data + idx, str, len);
362 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
364 char *name = mono_string_to_utf8 (str);
366 idx = string_heap_insert (sh, name);
371 #ifndef DISABLE_REFLECTION_EMIT
373 string_heap_init (MonoDynamicStream *sh)
376 sh->alloc_size = 4096;
377 sh->data = g_malloc (4096);
378 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
379 string_heap_insert (sh, "");
384 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
388 make_room_in_stream (stream, stream->index + len);
389 memcpy (stream->data + stream->index, data, len);
391 stream->index += len;
393 * align index? Not without adding an additional param that controls it since
394 * we may store a blob value in pieces.
400 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
404 make_room_in_stream (stream, stream->index + len);
405 memset (stream->data + stream->index, 0, len);
407 stream->index += len;
412 stream_data_align (MonoDynamicStream *stream)
415 guint32 count = stream->index % 4;
417 /* we assume the stream data will be aligned */
419 mono_image_add_stream_data (stream, buf, 4 - count);
422 #ifndef DISABLE_REFLECTION_EMIT
424 mono_blob_entry_hash (const char* str)
428 len = mono_metadata_decode_blob_size (str, &str);
432 for (str += 1; str < end; str++)
433 h = (h << 5) - h + *str;
441 mono_blob_entry_equal (const char *str1, const char *str2) {
445 len = mono_metadata_decode_blob_size (str1, &end1);
446 len2 = mono_metadata_decode_blob_size (str2, &end2);
449 return memcmp (end1, end2, len) == 0;
453 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
457 gpointer oldkey, oldval;
459 copy = g_malloc (s1+s2);
460 memcpy (copy, b1, s1);
461 memcpy (copy + s1, b2, s2);
462 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
464 idx = GPOINTER_TO_UINT (oldval);
466 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
467 mono_image_add_stream_data (&assembly->blob, b2, s2);
468 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
474 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
478 guint32 size = buf->p - buf->buf;
480 g_assert (size <= (buf->end - buf->buf));
481 mono_metadata_encode_value (size, b, &b);
482 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
486 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
487 * dest may be misaligned.
490 swap_with_size (char *dest, const char* val, int len, int nelem) {
491 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
494 for (elem = 0; elem < nelem; ++elem) {
520 g_assert_not_reached ();
526 memcpy (dest, val, len * nelem);
531 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
535 guint32 idx = 0, len;
537 len = str->length * 2;
538 mono_metadata_encode_value (len, b, &b);
539 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
541 char *swapped = g_malloc (2 * mono_string_length (str));
542 const char *p = (const char*)mono_string_chars (str);
544 swap_with_size (swapped, p, 2, mono_string_length (str));
545 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
549 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
554 #ifndef DISABLE_REFLECTION_EMIT
556 default_class_from_mono_type (MonoType *type)
558 switch (type->type) {
559 case MONO_TYPE_OBJECT:
560 return mono_defaults.object_class;
562 return mono_defaults.void_class;
563 case MONO_TYPE_BOOLEAN:
564 return mono_defaults.boolean_class;
566 return mono_defaults.char_class;
568 return mono_defaults.sbyte_class;
570 return mono_defaults.byte_class;
572 return mono_defaults.int16_class;
574 return mono_defaults.uint16_class;
576 return mono_defaults.int32_class;
578 return mono_defaults.uint32_class;
580 return mono_defaults.int_class;
582 return mono_defaults.uint_class;
584 return mono_defaults.int64_class;
586 return mono_defaults.uint64_class;
588 return mono_defaults.single_class;
590 return mono_defaults.double_class;
591 case MONO_TYPE_STRING:
592 return mono_defaults.string_class;
594 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
595 g_assert_not_reached ();
603 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
606 MonoGenericInst *class_inst;
611 class_inst = gclass->context.class_inst;
613 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
614 klass = gclass->container_class;
615 sigbuffer_add_value (buf, klass->byval_arg.type);
616 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
618 sigbuffer_add_value (buf, class_inst->type_argc);
619 for (i = 0; i < class_inst->type_argc; ++i)
620 encode_type (assembly, class_inst->type_argv [i], buf);
625 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
628 g_assert_not_reached ();
633 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
637 case MONO_TYPE_BOOLEAN:
651 case MONO_TYPE_STRING:
652 case MONO_TYPE_OBJECT:
653 case MONO_TYPE_TYPEDBYREF:
654 sigbuffer_add_value (buf, type->type);
657 sigbuffer_add_value (buf, type->type);
658 encode_type (assembly, type->data.type, buf);
660 case MONO_TYPE_SZARRAY:
661 sigbuffer_add_value (buf, type->type);
662 encode_type (assembly, &type->data.klass->byval_arg, buf);
664 case MONO_TYPE_VALUETYPE:
665 case MONO_TYPE_CLASS: {
666 MonoClass *k = mono_class_from_mono_type (type);
668 if (k->generic_container) {
669 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
670 encode_generic_class (assembly, gclass, buf);
673 * Make sure we use the correct type.
675 sigbuffer_add_value (buf, k->byval_arg.type);
677 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
678 * otherwise two typerefs could point to the same type, leading to
679 * verification errors.
681 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
685 case MONO_TYPE_ARRAY:
686 sigbuffer_add_value (buf, type->type);
687 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
688 sigbuffer_add_value (buf, type->data.array->rank);
689 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
690 sigbuffer_add_value (buf, 0);
692 case MONO_TYPE_GENERICINST:
693 encode_generic_class (assembly, type->data.generic_class, buf);
697 sigbuffer_add_value (buf, type->type);
698 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
701 g_error ("need to encode type %x", type->type);
706 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
709 sigbuffer_add_value (buf, MONO_TYPE_VOID);
713 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
717 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
722 for (i = 0; i < mono_array_length (modreq); ++i) {
723 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
724 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
725 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
729 for (i = 0; i < mono_array_length (modopt); ++i) {
730 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
731 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
732 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
737 #ifndef DISABLE_REFLECTION_EMIT
739 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
743 guint32 nparams = sig->param_count;
749 sigbuffer_init (&buf, 32);
751 * FIXME: vararg, explicit_this, differenc call_conv values...
753 idx = sig->call_convention;
755 idx |= 0x20; /* hasthis */
756 if (sig->generic_param_count)
757 idx |= 0x10; /* generic */
758 sigbuffer_add_byte (&buf, idx);
759 if (sig->generic_param_count)
760 sigbuffer_add_value (&buf, sig->generic_param_count);
761 sigbuffer_add_value (&buf, nparams);
762 encode_type (assembly, sig->ret, &buf);
763 for (i = 0; i < nparams; ++i) {
764 if (i == sig->sentinelpos)
765 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
766 encode_type (assembly, sig->params [i], &buf);
768 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
769 sigbuffer_free (&buf);
775 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
778 * FIXME: reuse code from method_encode_signature().
782 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
783 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
784 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
787 sigbuffer_init (&buf, 32);
788 /* LAMESPEC: all the call conv spec is foobared */
789 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
790 if (mb->call_conv & 2)
791 idx |= 0x5; /* vararg */
792 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
793 idx |= 0x20; /* hasthis */
795 idx |= 0x10; /* generic */
796 sigbuffer_add_byte (&buf, idx);
798 sigbuffer_add_value (&buf, ngparams);
799 sigbuffer_add_value (&buf, nparams + notypes);
800 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
801 encode_reflection_type (assembly, mb->rtype, &buf);
802 for (i = 0; i < nparams; ++i) {
803 MonoArray *modreq = NULL;
804 MonoArray *modopt = NULL;
805 MonoReflectionType *pt;
807 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
808 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
809 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
810 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
811 encode_custom_modifiers (assembly, modreq, modopt, &buf);
812 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
813 encode_reflection_type (assembly, pt, &buf);
816 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817 for (i = 0; i < notypes; ++i) {
818 MonoReflectionType *pt;
820 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
821 encode_reflection_type (assembly, pt, &buf);
824 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
825 sigbuffer_free (&buf);
830 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
832 MonoDynamicTable *table;
834 guint32 idx, sig_idx;
835 guint nl = mono_array_length (ilgen->locals);
839 sigbuffer_init (&buf, 32);
840 sigbuffer_add_value (&buf, 0x07);
841 sigbuffer_add_value (&buf, nl);
842 for (i = 0; i < nl; ++i) {
843 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
846 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
848 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
850 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
851 sigbuffer_free (&buf);
853 if (assembly->standalonesig_cache == NULL)
854 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
855 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
859 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
860 idx = table->next_idx ++;
862 alloc_table (table, table->rows);
863 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
865 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
867 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
873 method_count_clauses (MonoReflectionILGen *ilgen)
875 guint32 num_clauses = 0;
878 MonoILExceptionInfo *ex_info;
879 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
880 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
881 if (ex_info->handlers)
882 num_clauses += mono_array_length (ex_info->handlers);
890 #ifndef DISABLE_REFLECTION_EMIT
891 static MonoExceptionClause*
892 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
894 MonoExceptionClause *clauses;
895 MonoExceptionClause *clause;
896 MonoILExceptionInfo *ex_info;
897 MonoILExceptionBlock *ex_block;
898 guint32 finally_start;
899 int i, j, clause_index;;
901 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
904 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
905 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
906 finally_start = ex_info->start + ex_info->len;
907 if (!ex_info->handlers)
909 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
910 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
911 clause = &(clauses [clause_index]);
913 clause->flags = ex_block->type;
914 clause->try_offset = ex_info->start;
916 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
917 clause->try_len = finally_start - ex_info->start;
919 clause->try_len = ex_info->len;
920 clause->handler_offset = ex_block->start;
921 clause->handler_len = ex_block->len;
922 if (ex_block->extype) {
923 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
925 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
926 clause->data.filter_offset = ex_block->filter_offset;
928 clause->data.filter_offset = 0;
930 finally_start = ex_block->start + ex_block->len;
938 #endif /* !DISABLE_REFLECTION_EMIT */
941 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
947 gint32 num_locals = 0;
948 gint32 num_exception = 0;
951 char fat_header [12];
954 guint32 local_sig = 0;
955 guint32 header_size = 12;
958 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
959 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
963 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
965 code = mb->ilgen->code;
966 code_size = mb->ilgen->code_len;
967 max_stack = mb->ilgen->max_stack;
968 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
969 if (mb->ilgen->ex_handlers)
970 num_exception = method_count_clauses (mb->ilgen);
974 char *name = mono_string_to_utf8 (mb->name);
975 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
976 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
979 mono_raise_exception (exception);
982 code_size = mono_array_length (code);
983 max_stack = 8; /* we probably need to run a verifier on the code... */
986 stream_data_align (&assembly->code);
988 /* check for exceptions, maxstack, locals */
989 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
991 if (code_size < 64 && !(code_size & 1)) {
992 flags = (code_size << 2) | 0x2;
993 } else if (code_size < 32 && (code_size & 1)) {
994 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
998 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
999 /* add to the fixup todo list */
1000 if (mb->ilgen && mb->ilgen->num_token_fixups)
1001 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1002 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1003 return assembly->text_rva + idx;
1007 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1009 * FIXME: need to set also the header size in fat_flags.
1010 * (and more sects and init locals flags)
1014 fat_flags |= METHOD_HEADER_MORE_SECTS;
1015 if (mb->init_locals)
1016 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1017 fat_header [0] = fat_flags;
1018 fat_header [1] = (header_size / 4 ) << 4;
1019 short_value = GUINT16_TO_LE (max_stack);
1020 memcpy (fat_header + 2, &short_value, 2);
1021 int_value = GUINT32_TO_LE (code_size);
1022 memcpy (fat_header + 4, &int_value, 4);
1023 int_value = GUINT32_TO_LE (local_sig);
1024 memcpy (fat_header + 8, &int_value, 4);
1025 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1026 /* add to the fixup todo list */
1027 if (mb->ilgen && mb->ilgen->num_token_fixups)
1028 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1030 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1031 if (num_exception) {
1032 unsigned char sheader [4];
1033 MonoILExceptionInfo * ex_info;
1034 MonoILExceptionBlock * ex_block;
1037 stream_data_align (&assembly->code);
1038 /* always use fat format for now */
1039 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1040 num_exception *= 6 * sizeof (guint32);
1041 num_exception += 4; /* include the size of the header */
1042 sheader [1] = num_exception & 0xff;
1043 sheader [2] = (num_exception >> 8) & 0xff;
1044 sheader [3] = (num_exception >> 16) & 0xff;
1045 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1046 /* fat header, so we are already aligned */
1048 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1049 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1050 if (ex_info->handlers) {
1051 int finally_start = ex_info->start + ex_info->len;
1052 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1054 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1056 val = GUINT32_TO_LE (ex_block->type);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 val = GUINT32_TO_LE (ex_info->start);
1060 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1061 /* need fault, too, probably */
1062 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1063 val = GUINT32_TO_LE (finally_start - ex_info->start);
1065 val = GUINT32_TO_LE (ex_info->len);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1067 /* handler offset */
1068 val = GUINT32_TO_LE (ex_block->start);
1069 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1071 val = GUINT32_TO_LE (ex_block->len);
1072 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1073 finally_start = ex_block->start + ex_block->len;
1074 if (ex_block->extype) {
1075 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1077 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1078 val = ex_block->filter_offset;
1082 val = GUINT32_TO_LE (val);
1083 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1084 /*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",
1085 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);*/
1088 g_error ("No clauses for ex info block %d", i);
1092 return assembly->text_rva + idx;
1096 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1099 MonoDynamicTable *table;
1102 table = &assembly->tables [table_idx];
1104 g_assert (col < table->columns);
1106 values = table->values + table->columns;
1107 for (i = 1; i <= table->rows; ++i) {
1108 if (values [col] == token)
1110 values += table->columns;
1116 * LOCKING: Acquires the loader lock.
1118 static MonoCustomAttrInfo*
1119 lookup_custom_attr (MonoImage *image, gpointer member)
1121 MonoCustomAttrInfo* res;
1123 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1128 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1132 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1134 /* FIXME: Need to do more checks */
1135 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1136 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1138 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1145 static MonoCustomAttrInfo*
1146 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1148 int i, index, count, not_visible;
1149 MonoCustomAttrInfo *ainfo;
1150 MonoReflectionCustomAttr *cattr;
1154 /* FIXME: check in assembly the Run flag is set */
1156 count = mono_array_length (cattrs);
1158 /* Skip nonpublic attributes since MS.NET seems to do the same */
1159 /* FIXME: This needs to be done more globally */
1161 for (i = 0; i < count; ++i) {
1162 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1163 if (!custom_attr_visible (image, cattr))
1166 count -= not_visible;
1168 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1170 ainfo->image = image;
1171 ainfo->num_attrs = count;
1172 ainfo->cached = alloc_img != NULL;
1174 for (i = 0; i < count; ++i) {
1175 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1176 if (custom_attr_visible (image, cattr)) {
1177 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1178 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1179 ainfo->attrs [index].ctor = cattr->ctor->method;
1180 ainfo->attrs [index].data = saved;
1181 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1189 #ifndef DISABLE_REFLECTION_EMIT
1191 * LOCKING: Acquires the loader lock.
1194 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1196 MonoCustomAttrInfo *ainfo, *tmp;
1198 if (!cattrs || !mono_array_length (cattrs))
1201 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1203 mono_loader_lock ();
1204 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1206 mono_custom_attrs_free (tmp);
1207 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1208 mono_loader_unlock ();
1214 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1221 * idx is the table index of the object
1222 * type is one of MONO_CUSTOM_ATTR_*
1225 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1227 MonoDynamicTable *table;
1228 MonoReflectionCustomAttr *cattr;
1230 guint32 count, i, token;
1232 char *p = blob_size;
1234 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1237 count = mono_array_length (cattrs);
1238 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1239 table->rows += count;
1240 alloc_table (table, table->rows);
1241 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1242 idx <<= MONO_CUSTOM_ATTR_BITS;
1244 for (i = 0; i < count; ++i) {
1245 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1246 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1247 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1248 type = mono_metadata_token_index (token);
1249 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1250 switch (mono_metadata_token_table (token)) {
1251 case MONO_TABLE_METHOD:
1252 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1254 case MONO_TABLE_MEMBERREF:
1255 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1258 g_warning ("got wrong token in custom attr");
1261 values [MONO_CUSTOM_ATTR_TYPE] = type;
1263 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1264 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1265 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1266 values += MONO_CUSTOM_ATTR_SIZE;
1272 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1274 MonoDynamicTable *table;
1276 guint32 count, i, idx;
1277 MonoReflectionPermissionSet *perm;
1282 count = mono_array_length (permissions);
1283 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1284 table->rows += count;
1285 alloc_table (table, table->rows);
1287 for (i = 0; i < mono_array_length (permissions); ++i) {
1288 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1290 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1292 idx = mono_metadata_token_index (parent_token);
1293 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1294 switch (mono_metadata_token_table (parent_token)) {
1295 case MONO_TABLE_TYPEDEF:
1296 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1298 case MONO_TABLE_METHOD:
1299 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1301 case MONO_TABLE_ASSEMBLY:
1302 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1305 g_assert_not_reached ();
1308 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1309 values [MONO_DECL_SECURITY_PARENT] = idx;
1310 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1317 * Fill in the MethodDef and ParamDef tables for a method.
1318 * This is used for both normal methods and constructors.
1321 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1323 MonoDynamicTable *table;
1327 /* room in this table is already allocated */
1328 table = &assembly->tables [MONO_TABLE_METHOD];
1329 *mb->table_idx = table->next_idx ++;
1330 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1331 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1332 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1333 values [MONO_METHOD_FLAGS] = mb->attrs;
1334 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1335 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1336 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1338 table = &assembly->tables [MONO_TABLE_PARAM];
1339 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1341 mono_image_add_decl_security (assembly,
1342 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1345 MonoDynamicTable *mtable;
1348 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1349 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1352 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1353 if (mono_array_get (mb->pinfo, gpointer, i))
1356 table->rows += count;
1357 alloc_table (table, table->rows);
1358 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1359 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1360 MonoReflectionParamBuilder *pb;
1361 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1362 values [MONO_PARAM_FLAGS] = pb->attrs;
1363 values [MONO_PARAM_SEQUENCE] = i;
1364 if (pb->name != NULL) {
1365 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1367 values [MONO_PARAM_NAME] = 0;
1369 values += MONO_PARAM_SIZE;
1370 if (pb->marshal_info) {
1372 alloc_table (mtable, mtable->rows);
1373 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1374 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1375 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1377 pb->table_idx = table->next_idx++;
1378 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1379 guint32 field_type = 0;
1380 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1382 alloc_table (mtable, mtable->rows);
1383 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1384 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1385 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1386 mvalues [MONO_CONSTANT_TYPE] = field_type;
1387 mvalues [MONO_CONSTANT_PADDING] = 0;
1395 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1397 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1399 rmb->ilgen = mb->ilgen;
1400 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1401 rmb->parameters = mb->parameters;
1402 rmb->generic_params = mb->generic_params;
1403 rmb->generic_container = mb->generic_container;
1404 rmb->opt_types = NULL;
1405 rmb->pinfo = mb->pinfo;
1406 rmb->attrs = mb->attrs;
1407 rmb->iattrs = mb->iattrs;
1408 rmb->call_conv = mb->call_conv;
1409 rmb->code = mb->code;
1410 rmb->type = mb->type;
1411 rmb->name = mb->name;
1412 rmb->table_idx = &mb->table_idx;
1413 rmb->init_locals = mb->init_locals;
1414 rmb->skip_visibility = FALSE;
1415 rmb->return_modreq = mb->return_modreq;
1416 rmb->return_modopt = mb->return_modopt;
1417 rmb->param_modreq = mb->param_modreq;
1418 rmb->param_modopt = mb->param_modopt;
1419 rmb->permissions = mb->permissions;
1420 rmb->mhandle = mb->mhandle;
1425 rmb->charset = mb->charset;
1426 rmb->extra_flags = mb->extra_flags;
1427 rmb->native_cc = mb->native_cc;
1428 rmb->dllentry = mb->dllentry;
1434 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1436 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1438 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1440 rmb->ilgen = mb->ilgen;
1441 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1442 rmb->parameters = mb->parameters;
1443 rmb->generic_params = NULL;
1444 rmb->generic_container = NULL;
1445 rmb->opt_types = NULL;
1446 rmb->pinfo = mb->pinfo;
1447 rmb->attrs = mb->attrs;
1448 rmb->iattrs = mb->iattrs;
1449 rmb->call_conv = mb->call_conv;
1451 rmb->type = mb->type;
1452 rmb->name = mono_string_new (mono_domain_get (), name);
1453 rmb->table_idx = &mb->table_idx;
1454 rmb->init_locals = mb->init_locals;
1455 rmb->skip_visibility = FALSE;
1456 rmb->return_modreq = NULL;
1457 rmb->return_modopt = NULL;
1458 rmb->param_modreq = mb->param_modreq;
1459 rmb->param_modopt = mb->param_modopt;
1460 rmb->permissions = mb->permissions;
1461 rmb->mhandle = mb->mhandle;
1466 #ifndef DISABLE_REFLECTION_EMIT
1468 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1470 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1472 rmb->ilgen = mb->ilgen;
1473 rmb->rtype = mb->rtype;
1474 rmb->parameters = mb->parameters;
1475 rmb->generic_params = NULL;
1476 rmb->generic_container = NULL;
1477 rmb->opt_types = NULL;
1479 rmb->attrs = mb->attrs;
1481 rmb->call_conv = mb->call_conv;
1483 rmb->type = (MonoObject *) mb->owner;
1484 rmb->name = mb->name;
1485 rmb->table_idx = NULL;
1486 rmb->init_locals = mb->init_locals;
1487 rmb->skip_visibility = mb->skip_visibility;
1488 rmb->return_modreq = NULL;
1489 rmb->return_modopt = NULL;
1490 rmb->param_modreq = NULL;
1491 rmb->param_modopt = NULL;
1492 rmb->permissions = NULL;
1493 rmb->mhandle = mb->mhandle;
1500 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1502 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1503 MonoDynamicTable *table;
1507 if (!mb->override_method)
1510 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1512 alloc_table (table, table->rows);
1513 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1514 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1515 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1517 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1518 switch (mono_metadata_token_table (tok)) {
1519 case MONO_TABLE_MEMBERREF:
1520 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1522 case MONO_TABLE_METHOD:
1523 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1526 g_assert_not_reached ();
1528 values [MONO_METHODIMPL_DECLARATION] = tok;
1532 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1534 MonoDynamicTable *table;
1536 ReflectionMethodBuilder rmb;
1539 reflection_methodbuilder_from_method_builder (&rmb, mb);
1541 mono_image_basic_method (&rmb, assembly);
1542 mb->table_idx = *rmb.table_idx;
1544 if (mb->dll) { /* It's a P/Invoke method */
1546 /* map CharSet values to on-disk values */
1547 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1548 int extra_flags = mb->extra_flags;
1549 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1551 alloc_table (table, table->rows);
1552 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1554 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1555 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1557 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1559 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1560 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1561 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1562 table = &assembly->tables [MONO_TABLE_MODULEREF];
1564 alloc_table (table, table->rows);
1565 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1566 values [MONO_IMPLMAP_SCOPE] = table->rows;
1570 if (mb->generic_params) {
1571 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1572 table->rows += mono_array_length (mb->generic_params);
1573 alloc_table (table, table->rows);
1574 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1575 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1577 mono_image_get_generic_param_info (
1578 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1585 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1587 ReflectionMethodBuilder rmb;
1589 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1591 mono_image_basic_method (&rmb, assembly);
1592 mb->table_idx = *rmb.table_idx;
1596 type_get_fully_qualified_name (MonoType *type)
1598 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1602 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1606 klass = mono_class_from_mono_type (type);
1608 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1609 ta = klass->image->assembly;
1610 if (ta->dynamic || (ta == ass)) {
1611 if (klass->generic_class || klass->generic_container)
1612 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1613 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1615 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1618 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1621 #ifndef DISABLE_REFLECTION_EMIT
1622 /*field_image is the image to which the eventual custom mods have been encoded against*/
1624 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1627 guint32 idx, i, token;
1629 if (!assembly->save)
1632 sigbuffer_init (&buf, 32);
1634 sigbuffer_add_value (&buf, 0x06);
1635 /* encode custom attributes before the type */
1636 if (type->num_mods) {
1637 for (i = 0; i < type->num_mods; ++i) {
1639 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1641 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1643 token = type->modifiers [i].token;
1646 if (type->modifiers [i].required)
1647 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1649 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1651 sigbuffer_add_value (&buf, token);
1654 encode_type (assembly, type, &buf);
1655 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1656 sigbuffer_free (&buf);
1662 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1667 sigbuffer_init (&buf, 32);
1669 sigbuffer_add_value (&buf, 0x06);
1670 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1671 /* encode custom attributes before the type */
1672 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1673 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1674 sigbuffer_free (&buf);
1679 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1680 char blob_size [64];
1681 char *b = blob_size;
1684 guint32 idx = 0, len = 0, dummy = 0;
1686 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1687 guint32 fpa_double [2];
1692 p = buf = g_malloc (64);
1694 *ret_type = MONO_TYPE_CLASS;
1696 box_val = (char*)&dummy;
1698 box_val = ((char*)val) + sizeof (MonoObject);
1699 *ret_type = val->vtable->klass->byval_arg.type;
1702 switch (*ret_type) {
1703 case MONO_TYPE_BOOLEAN:
1708 case MONO_TYPE_CHAR:
1725 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1726 fpa_p = (guint32*)box_val;
1727 fpa_double [0] = fpa_p [1];
1728 fpa_double [1] = fpa_p [0];
1729 box_val = (char*)fpa_double;
1733 case MONO_TYPE_VALUETYPE:
1734 if (val->vtable->klass->enumtype) {
1735 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1738 g_error ("we can't encode valuetypes");
1739 case MONO_TYPE_CLASS:
1741 case MONO_TYPE_STRING: {
1742 MonoString *str = (MonoString*)val;
1743 /* there is no signature */
1744 len = str->length * 2;
1745 mono_metadata_encode_value (len, b, &b);
1746 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1748 char *swapped = g_malloc (2 * mono_string_length (str));
1749 const char *p = (const char*)mono_string_chars (str);
1751 swap_with_size (swapped, p, 2, mono_string_length (str));
1752 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1756 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1762 case MONO_TYPE_GENERICINST:
1763 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1766 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1769 /* there is no signature */
1770 mono_metadata_encode_value (len, b, &b);
1771 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1772 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1773 swap_with_size (blob_size, box_val, len, 1);
1774 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1776 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1784 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1789 sigbuffer_init (&buf, 32);
1791 sigbuffer_add_value (&buf, minfo->type);
1793 switch (minfo->type) {
1794 case MONO_NATIVE_BYVALTSTR:
1795 case MONO_NATIVE_BYVALARRAY:
1796 sigbuffer_add_value (&buf, minfo->count);
1798 case MONO_NATIVE_LPARRAY:
1799 if (minfo->eltype || minfo->has_size) {
1800 sigbuffer_add_value (&buf, minfo->eltype);
1801 if (minfo->has_size) {
1802 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1803 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1805 /* LAMESPEC: ElemMult is undocumented */
1806 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1810 case MONO_NATIVE_SAFEARRAY:
1812 sigbuffer_add_value (&buf, minfo->eltype);
1814 case MONO_NATIVE_CUSTOM:
1816 str = mono_string_to_utf8 (minfo->guid);
1818 sigbuffer_add_value (&buf, len);
1819 sigbuffer_add_mem (&buf, str, len);
1822 sigbuffer_add_value (&buf, 0);
1824 /* native type name */
1825 sigbuffer_add_value (&buf, 0);
1826 /* custom marshaler type name */
1827 if (minfo->marshaltype || minfo->marshaltyperef) {
1828 if (minfo->marshaltyperef)
1829 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1831 str = mono_string_to_utf8 (minfo->marshaltype);
1833 sigbuffer_add_value (&buf, len);
1834 sigbuffer_add_mem (&buf, str, len);
1837 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1838 sigbuffer_add_value (&buf, 0);
1840 if (minfo->mcookie) {
1841 str = mono_string_to_utf8 (minfo->mcookie);
1843 sigbuffer_add_value (&buf, len);
1844 sigbuffer_add_mem (&buf, str, len);
1847 sigbuffer_add_value (&buf, 0);
1853 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1854 sigbuffer_free (&buf);
1859 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1861 MonoDynamicTable *table;
1864 /* maybe this fixup should be done in the C# code */
1865 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1866 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1867 table = &assembly->tables [MONO_TABLE_FIELD];
1868 fb->table_idx = table->next_idx ++;
1869 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1870 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1871 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1872 values [MONO_FIELD_FLAGS] = fb->attrs;
1873 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1875 if (fb->offset != -1) {
1876 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1878 alloc_table (table, table->rows);
1879 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1880 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1881 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1883 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1884 guint32 field_type = 0;
1885 table = &assembly->tables [MONO_TABLE_CONSTANT];
1887 alloc_table (table, table->rows);
1888 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1889 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1890 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1891 values [MONO_CONSTANT_TYPE] = field_type;
1892 values [MONO_CONSTANT_PADDING] = 0;
1894 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1896 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1898 alloc_table (table, table->rows);
1899 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1900 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1902 * We store it in the code section because it's simpler for now.
1905 if (mono_array_length (fb->rva_data) >= 10)
1906 stream_data_align (&assembly->code);
1907 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1909 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1910 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1912 if (fb->marshal_info) {
1913 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1915 alloc_table (table, table->rows);
1916 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1917 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1918 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1923 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1926 guint32 nparams = 0;
1927 MonoReflectionMethodBuilder *mb = fb->get_method;
1928 MonoReflectionMethodBuilder *smb = fb->set_method;
1931 if (mb && mb->parameters)
1932 nparams = mono_array_length (mb->parameters);
1933 if (!mb && smb && smb->parameters)
1934 nparams = mono_array_length (smb->parameters) - 1;
1935 sigbuffer_init (&buf, 32);
1936 sigbuffer_add_byte (&buf, 0x08);
1937 sigbuffer_add_value (&buf, nparams);
1939 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1940 for (i = 0; i < nparams; ++i) {
1941 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1942 encode_reflection_type (assembly, pt, &buf);
1944 } else if (smb && smb->parameters) {
1945 /* the property type is the last param */
1946 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1947 for (i = 0; i < nparams; ++i) {
1948 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1949 encode_reflection_type (assembly, pt, &buf);
1952 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1955 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1956 sigbuffer_free (&buf);
1961 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1963 MonoDynamicTable *table;
1965 guint num_methods = 0;
1969 * we need to set things in the following tables:
1970 * PROPERTYMAP (info already filled in _get_type_info ())
1971 * PROPERTY (rows already preallocated in _get_type_info ())
1972 * METHOD (method info already done with the generic method code)
1975 table = &assembly->tables [MONO_TABLE_PROPERTY];
1976 pb->table_idx = table->next_idx ++;
1977 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1978 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1979 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1980 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1982 /* FIXME: we still don't handle 'other' methods */
1983 if (pb->get_method) num_methods ++;
1984 if (pb->set_method) num_methods ++;
1986 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1987 table->rows += num_methods;
1988 alloc_table (table, table->rows);
1990 if (pb->get_method) {
1991 semaidx = table->next_idx ++;
1992 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1993 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1994 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1995 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1997 if (pb->set_method) {
1998 semaidx = table->next_idx ++;
1999 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2000 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2001 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2002 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2007 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2009 MonoDynamicTable *table;
2011 guint num_methods = 0;
2015 * we need to set things in the following tables:
2016 * EVENTMAP (info already filled in _get_type_info ())
2017 * EVENT (rows already preallocated in _get_type_info ())
2018 * METHOD (method info already done with the generic method code)
2021 table = &assembly->tables [MONO_TABLE_EVENT];
2022 eb->table_idx = table->next_idx ++;
2023 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2024 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2025 values [MONO_EVENT_FLAGS] = eb->attrs;
2026 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2029 * FIXME: we still don't handle 'other' methods
2031 if (eb->add_method) num_methods ++;
2032 if (eb->remove_method) num_methods ++;
2033 if (eb->raise_method) num_methods ++;
2035 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2036 table->rows += num_methods;
2037 alloc_table (table, table->rows);
2039 if (eb->add_method) {
2040 semaidx = table->next_idx ++;
2041 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2042 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2043 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2044 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2046 if (eb->remove_method) {
2047 semaidx = table->next_idx ++;
2048 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2049 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2050 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2051 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2053 if (eb->raise_method) {
2054 semaidx = table->next_idx ++;
2055 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2056 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2057 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2058 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2063 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2065 MonoDynamicTable *table;
2066 guint32 num_constraints, i;
2070 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2071 num_constraints = gparam->iface_constraints ?
2072 mono_array_length (gparam->iface_constraints) : 0;
2073 table->rows += num_constraints;
2074 if (gparam->base_type)
2076 alloc_table (table, table->rows);
2078 if (gparam->base_type) {
2079 table_idx = table->next_idx ++;
2080 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2082 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2083 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2084 assembly, mono_reflection_type_get_handle (gparam->base_type));
2087 for (i = 0; i < num_constraints; i++) {
2088 MonoReflectionType *constraint = mono_array_get (
2089 gparam->iface_constraints, gpointer, i);
2091 table_idx = table->next_idx ++;
2092 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2094 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2095 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2096 assembly, mono_reflection_type_get_handle (constraint));
2101 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2103 GenericParamTableEntry *entry;
2106 * The GenericParam table must be sorted according to the `owner' field.
2107 * We need to do this sorting prior to writing the GenericParamConstraint
2108 * table, since we have to use the final GenericParam table indices there
2109 * and they must also be sorted.
2112 entry = g_new0 (GenericParamTableEntry, 1);
2113 entry->owner = owner;
2114 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2115 MOVING_GC_REGISTER (&entry->gparam);
2116 entry->gparam = gparam;
2118 g_ptr_array_add (assembly->gen_params, entry);
2122 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2124 MonoDynamicTable *table;
2125 MonoGenericParam *param;
2129 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2130 table_idx = table->next_idx ++;
2131 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2133 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2135 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2136 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2137 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2138 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2140 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2142 encode_constraints (entry->gparam, table_idx, assembly);
2146 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2148 MonoDynamicTable *table;
2151 guint32 cols [MONO_ASSEMBLY_SIZE];
2155 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2158 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2159 table = &assembly->tables [MONO_TABLE_MODULEREF];
2160 token = table->next_idx ++;
2162 alloc_table (table, table->rows);
2163 values = table->values + token * MONO_MODULEREF_SIZE;
2164 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2166 token <<= MONO_RESOLTION_SCOPE_BITS;
2167 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2168 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2173 if (image->assembly->dynamic)
2175 memset (cols, 0, sizeof (cols));
2177 /* image->assembly->image is the manifest module */
2178 image = image->assembly->image;
2179 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2182 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2183 token = table->next_idx ++;
2185 alloc_table (table, table->rows);
2186 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2187 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2188 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2189 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2190 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2191 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2192 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2193 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2194 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2196 if (strcmp ("", image->assembly->aname.culture)) {
2197 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2198 image->assembly->aname.culture);
2201 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2202 guchar pubtoken [9];
2204 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2205 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2207 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2209 token <<= MONO_RESOLTION_SCOPE_BITS;
2210 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2211 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2216 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2218 MonoDynamicTable *table;
2223 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2226 sigbuffer_init (&buf, 32);
2227 switch (type->type) {
2228 case MONO_TYPE_FNPTR:
2230 case MONO_TYPE_SZARRAY:
2231 case MONO_TYPE_ARRAY:
2233 case MONO_TYPE_MVAR:
2234 case MONO_TYPE_GENERICINST:
2235 encode_type (assembly, type, &buf);
2237 case MONO_TYPE_CLASS:
2238 case MONO_TYPE_VALUETYPE: {
2239 MonoClass *k = mono_class_from_mono_type (type);
2240 if (!k || !k->generic_container) {
2241 sigbuffer_free (&buf);
2244 encode_type (assembly, type, &buf);
2248 sigbuffer_free (&buf);
2252 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2253 if (assembly->save) {
2254 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2255 alloc_table (table, table->rows + 1);
2256 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2257 values [MONO_TYPESPEC_SIGNATURE] = token;
2259 sigbuffer_free (&buf);
2261 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2262 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2268 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2270 MonoDynamicTable *table;
2272 guint32 token, scope, enclosing;
2275 /* if the type requires a typespec, we must try that first*/
2276 if (try_typespec && (token = create_typespec (assembly, type)))
2278 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2281 klass = mono_class_from_mono_type (type);
2283 klass = mono_class_from_mono_type (type);
2286 * If it's in the same module and not a generic type parameter:
2288 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2289 (type->type != MONO_TYPE_MVAR)) {
2290 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2291 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2292 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2296 if (klass->nested_in) {
2297 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2298 /* get the typeref idx of the enclosing type */
2299 enclosing >>= MONO_TYPEDEFORREF_BITS;
2300 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2302 scope = resolution_scope_from_image (assembly, klass->image);
2304 table = &assembly->tables [MONO_TABLE_TYPEREF];
2305 if (assembly->save) {
2306 alloc_table (table, table->rows + 1);
2307 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2308 values [MONO_TYPEREF_SCOPE] = scope;
2309 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2310 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2312 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2313 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2315 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2320 * Despite the name, we handle also TypeSpec (with the above helper).
2323 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2325 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2328 #ifndef DISABLE_REFLECTION_EMIT
2330 * Insert a memberef row into the metadata: the token that point to the memberref
2331 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2332 * mono_image_get_fieldref_token()).
2333 * The sig param is an index to an already built signature.
2336 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2338 MonoDynamicTable *table;
2340 guint32 token, pclass;
2343 parent = mono_image_typedef_or_ref (assembly, type);
2344 switch (parent & MONO_TYPEDEFORREF_MASK) {
2345 case MONO_TYPEDEFORREF_TYPEREF:
2346 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2348 case MONO_TYPEDEFORREF_TYPESPEC:
2349 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2351 case MONO_TYPEDEFORREF_TYPEDEF:
2352 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2355 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2358 /* extract the index */
2359 parent >>= MONO_TYPEDEFORREF_BITS;
2361 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2363 if (assembly->save) {
2364 alloc_table (table, table->rows + 1);
2365 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2366 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2367 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2368 values [MONO_MEMBERREF_SIGNATURE] = sig;
2371 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2378 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2381 MonoMethodSignature *sig;
2383 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2385 if (create_typespec) {
2386 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2391 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2392 if (token && !create_typespec)
2395 g_assert (!method->is_inflated);
2398 * A methodref signature can't contain an unmanaged calling convention.
2400 sig = mono_metadata_signature_dup (mono_method_signature (method));
2401 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2402 sig->call_convention = MONO_CALL_DEFAULT;
2403 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2404 method->name, method_encode_signature (assembly, sig));
2406 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2409 if (create_typespec) {
2410 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2411 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2412 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2414 if (assembly->save) {
2417 alloc_table (table, table->rows + 1);
2418 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2419 values [MONO_METHODSPEC_METHOD] = token;
2420 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2423 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2425 /*methodspec and memberef tokens are diferent, */
2426 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2433 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2436 ReflectionMethodBuilder rmb;
2439 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2443 name = mono_string_to_utf8 (method->name);
2444 reflection_methodbuilder_from_method_builder (&rmb, method);
2447 * A methodref signature can't contain an unmanaged calling convention.
2448 * Since some flags are encoded as part of call_conv, we need to check against it.
2450 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2451 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2452 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2453 name, method_builder_encode_signature (assembly, &rmb));
2456 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2461 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2462 const gchar *name, guint32 sig)
2464 MonoDynamicTable *table;
2468 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2470 if (assembly->save) {
2471 alloc_table (table, table->rows + 1);
2472 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2473 values [MONO_MEMBERREF_CLASS] = original;
2474 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2475 values [MONO_MEMBERREF_SIGNATURE] = sig;
2478 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2485 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2489 guint32 nparams = mono_array_length (mb->generic_params);
2492 if (!assembly->save)
2495 sigbuffer_init (&buf, 32);
2497 sigbuffer_add_value (&buf, 0xa);
2498 sigbuffer_add_value (&buf, nparams);
2500 for (i = 0; i < nparams; i++) {
2501 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2502 sigbuffer_add_value (&buf, i);
2505 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2506 sigbuffer_free (&buf);
2511 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2513 MonoDynamicTable *table;
2515 guint32 token, mtoken = 0;
2517 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2521 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2523 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2524 switch (mono_metadata_token_table (mtoken)) {
2525 case MONO_TABLE_MEMBERREF:
2526 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2528 case MONO_TABLE_METHOD:
2529 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2532 g_assert_not_reached ();
2535 if (assembly->save) {
2536 alloc_table (table, table->rows + 1);
2537 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2538 values [MONO_METHODSPEC_METHOD] = mtoken;
2539 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2542 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2545 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2550 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2554 if (mb->generic_params && create_methodspec)
2555 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2557 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2561 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2562 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2567 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2570 ReflectionMethodBuilder rmb;
2573 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2577 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2579 name = mono_string_to_utf8 (rmb.name);
2580 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2581 name, method_builder_encode_signature (assembly, &rmb));
2584 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2590 is_field_on_inst (MonoClassField *field)
2592 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2596 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2599 get_field_on_inst_generic_type (MonoClassField *field)
2601 MonoDynamicGenericClass *dgclass;
2604 g_assert (is_field_on_inst (field));
2606 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2607 field_index = field - dgclass->fields;
2609 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2610 return dgclass->field_generic_types [field_index];
2613 #ifndef DISABLE_REFLECTION_EMIT
2615 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2619 MonoClassField *field;
2621 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2624 g_assert (f->field->parent);
2627 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2628 int index = field - field->parent->fields;
2629 type = field->parent->generic_class->container_class->fields [index].type;
2631 if (is_field_on_inst (f->field))
2632 type = get_field_on_inst_generic_type (f->field);
2634 type = f->field->type;
2636 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2637 mono_field_get_name (f->field),
2638 fieldref_encode_signature (assembly, field->parent->image, type));
2639 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2644 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2648 MonoGenericClass *gclass;
2649 MonoDynamicGenericClass *dgclass;
2650 MonoReflectionFieldBuilder *fb = f->fb;
2654 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2657 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2658 klass = mono_class_from_mono_type (type);
2659 gclass = type->data.generic_class;
2660 g_assert (gclass->is_dynamic);
2661 dgclass = (MonoDynamicGenericClass *) gclass;
2663 name = mono_string_to_utf8 (fb->name);
2664 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2665 field_encode_signature (assembly, fb));
2667 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2672 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2676 MonoGenericClass *gclass;
2677 MonoDynamicGenericClass *dgclass;
2678 MonoReflectionCtorBuilder *cb = c->cb;
2679 ReflectionMethodBuilder rmb;
2683 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2685 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2688 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2689 klass = mono_class_from_mono_type (type);
2690 gclass = type->data.generic_class;
2691 g_assert (gclass->is_dynamic);
2692 dgclass = (MonoDynamicGenericClass *) gclass;
2694 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2696 name = mono_string_to_utf8 (rmb.name);
2698 sig = method_builder_encode_signature (assembly, &rmb);
2700 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2703 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2708 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2711 MonoGenericContext tmp_context;
2712 MonoType **type_argv;
2713 MonoGenericInst *ginst;
2714 MonoMethod *method, *inflated;
2717 method = inflate_method (m->inst, (MonoObject*)m->mb);
2719 klass = method->klass;
2721 if (method->is_inflated)
2722 method = ((MonoMethodInflated *) method)->declaring;
2724 count = mono_array_length (m->method_args);
2726 type_argv = g_new0 (MonoType *, count);
2727 for (i = 0; i < count; i++) {
2728 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2729 type_argv [i] = mono_reflection_type_get_handle (garg);
2731 ginst = mono_metadata_get_generic_inst (count, type_argv);
2734 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2735 tmp_context.method_inst = ginst;
2737 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2742 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2746 MonoGenericClass *gclass;
2747 MonoReflectionMethodBuilder *mb = m->mb;
2748 ReflectionMethodBuilder rmb;
2752 if (m->method_args) {
2753 MonoMethod *inflated;
2755 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2756 if (create_methodspec)
2757 token = mono_image_get_methodspec_token (assembly, inflated);
2759 token = mono_image_get_inflated_method_token (assembly, inflated);
2763 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2766 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2767 klass = mono_class_from_mono_type (type);
2768 gclass = type->data.generic_class;
2769 g_assert (gclass->is_dynamic);
2771 reflection_methodbuilder_from_method_builder (&rmb, mb);
2773 name = mono_string_to_utf8 (rmb.name);
2775 sig = method_builder_encode_signature (assembly, &rmb);
2777 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2780 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2785 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2789 guint32 nparams = context->method_inst->type_argc;
2792 if (!assembly->save)
2795 sigbuffer_init (&buf, 32);
2797 * FIXME: vararg, explicit_this, differenc call_conv values...
2799 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2800 sigbuffer_add_value (&buf, nparams);
2802 for (i = 0; i < nparams; i++)
2803 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2805 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2806 sigbuffer_free (&buf);
2811 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2813 MonoDynamicTable *table;
2815 guint32 token, mtoken = 0, sig;
2816 MonoMethodInflated *imethod;
2817 MonoMethod *declaring;
2819 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2821 g_assert (method->is_inflated);
2822 imethod = (MonoMethodInflated *) method;
2823 declaring = imethod->declaring;
2825 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2826 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2828 if (!mono_method_signature (declaring)->generic_param_count)
2831 switch (mono_metadata_token_table (mtoken)) {
2832 case MONO_TABLE_MEMBERREF:
2833 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2835 case MONO_TABLE_METHOD:
2836 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2839 g_assert_not_reached ();
2842 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2844 if (assembly->save) {
2845 alloc_table (table, table->rows + 1);
2846 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2847 values [MONO_METHODSPEC_METHOD] = mtoken;
2848 values [MONO_METHODSPEC_SIGNATURE] = sig;
2851 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2858 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2860 MonoMethodInflated *imethod;
2863 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2867 g_assert (method->is_inflated);
2868 imethod = (MonoMethodInflated *) method;
2870 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2871 token = method_encode_methodspec (assembly, method);
2873 guint32 sig = method_encode_signature (
2874 assembly, mono_method_signature (imethod->declaring));
2875 token = mono_image_get_memberref_token (
2876 assembly, &method->klass->byval_arg, method->name, sig);
2879 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2884 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2886 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2889 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2890 token = mono_image_get_memberref_token (
2891 assembly, &m->klass->byval_arg, m->name, sig);
2897 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2899 MonoDynamicTable *table;
2908 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2909 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2910 * Because of this, we must not insert it into the `typeref' hash table.
2912 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2913 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2917 sigbuffer_init (&buf, 32);
2919 g_assert (tb->generic_params);
2920 klass = mono_class_from_mono_type (type);
2922 if (tb->generic_container)
2923 mono_reflection_create_generic_class (tb);
2925 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2926 g_assert (klass->generic_container);
2927 sigbuffer_add_value (&buf, klass->byval_arg.type);
2928 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2930 count = mono_array_length (tb->generic_params);
2931 sigbuffer_add_value (&buf, count);
2932 for (i = 0; i < count; i++) {
2933 MonoReflectionGenericParam *gparam;
2935 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2937 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
2940 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2942 if (assembly->save) {
2943 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2944 alloc_table (table, table->rows + 1);
2945 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2946 values [MONO_TYPESPEC_SIGNATURE] = token;
2948 sigbuffer_free (&buf);
2950 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2951 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2957 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2960 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2962 int i, count, len, pos;
2967 count += mono_array_length (modreq);
2969 count += mono_array_length (modopt);
2972 return mono_metadata_type_dup (NULL, type);
2974 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
2976 memcpy (t, type, MONO_SIZEOF_TYPE);
2978 t->num_mods = count;
2981 for (i = 0; i < mono_array_length (modreq); ++i) {
2982 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
2983 t->modifiers [pos].required = 1;
2984 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
2989 for (i = 0; i < mono_array_length (modopt); ++i) {
2990 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
2991 t->modifiers [pos].required = 0;
2992 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3001 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3003 MonoDynamicTable *table;
3005 MonoType *custom = NULL;
3007 guint32 token, pclass, parent, sig;
3010 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
3014 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3015 name = mono_string_to_utf8 (fb->name);
3017 /* fb->type does not include the custom modifiers */
3018 /* FIXME: We should do this in one place when a fieldbuilder is created */
3019 if (fb->modreq || fb->modopt) {
3020 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3021 sig = fieldref_encode_signature (assembly, NULL, custom);
3024 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3027 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3028 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3030 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3031 parent >>= MONO_TYPEDEFORREF_BITS;
3033 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3035 if (assembly->save) {
3036 alloc_table (table, table->rows + 1);
3037 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3038 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3039 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3040 values [MONO_MEMBERREF_SIGNATURE] = sig;
3043 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3045 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3051 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3058 if (!assembly->save)
3061 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3062 g_assert (helper->type == 2);
3064 if (helper->arguments)
3065 nargs = mono_array_length (helper->arguments);
3069 size = 10 + (nargs * 10);
3071 sigbuffer_init (&buf, 32);
3073 /* Encode calling convention */
3074 /* Change Any to Standard */
3075 if ((helper->call_conv & 0x03) == 0x03)
3076 helper->call_conv = 0x01;
3077 /* explicit_this implies has_this */
3078 if (helper->call_conv & 0x40)
3079 helper->call_conv &= 0x20;
3081 if (helper->call_conv == 0) { /* Unmanaged */
3082 idx = helper->unmanaged_call_conv - 1;
3085 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3086 if (helper->call_conv & 0x02) /* varargs */
3090 sigbuffer_add_byte (&buf, idx);
3091 sigbuffer_add_value (&buf, nargs);
3092 encode_reflection_type (assembly, helper->return_type, &buf);
3093 for (i = 0; i < nargs; ++i) {
3094 MonoArray *modreqs = NULL;
3095 MonoArray *modopts = NULL;
3096 MonoReflectionType *pt;
3098 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3099 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3100 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3101 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3103 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3104 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3105 encode_reflection_type (assembly, pt, &buf);
3107 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3108 sigbuffer_free (&buf);
3114 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3117 MonoDynamicTable *table;
3120 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3121 idx = table->next_idx ++;
3123 alloc_table (table, table->rows);
3124 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3126 values [MONO_STAND_ALONE_SIGNATURE] =
3127 mono_reflection_encode_sighelper (assembly, helper);
3133 reflection_cc_to_file (int call_conv) {
3134 switch (call_conv & 0x3) {
3136 case 1: return MONO_CALL_DEFAULT;
3137 case 2: return MONO_CALL_VARARG;
3139 g_assert_not_reached ();
3143 #endif /* !DISABLE_REFLECTION_EMIT */
3147 MonoMethodSignature *sig;
3152 #ifndef DISABLE_REFLECTION_EMIT
3154 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3159 MonoMethodSignature *sig;
3163 name = mono_string_to_utf8 (m->name);
3164 nparams = mono_array_length (m->parameters);
3165 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3167 sig->sentinelpos = -1;
3168 sig->call_convention = reflection_cc_to_file (m->call_conv);
3169 sig->param_count = nparams;
3170 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3171 mtype = mono_reflection_type_get_handle (m->parent);
3172 for (i = 0; i < nparams; ++i)
3173 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3175 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3177 if (strcmp (name, am->name) == 0 &&
3178 mono_metadata_type_equal (am->parent, mtype) &&
3179 mono_metadata_signature_equal (am->sig, sig)) {
3182 m->table_idx = am->token & 0xffffff;
3186 am = g_new0 (ArrayMethod, 1);
3190 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3191 method_encode_signature (assembly, sig));
3192 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3193 m->table_idx = am->token & 0xffffff;
3199 * Insert into the metadata tables all the info about the TypeBuilder tb.
3200 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3203 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3205 MonoDynamicTable *table;
3207 int i, is_object = 0, is_system = 0;
3210 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3211 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3212 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3213 n = mono_string_to_utf8 (tb->name);
3214 if (strcmp (n, "Object") == 0)
3216 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3218 n = mono_string_to_utf8 (tb->nspace);
3219 if (strcmp (n, "System") == 0)
3221 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3223 if (tb->parent && !(is_system && is_object) &&
3224 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3225 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3227 values [MONO_TYPEDEF_EXTENDS] = 0;
3229 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3230 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3233 * if we have explicitlayout or sequentiallayouts, output data in the
3234 * ClassLayout table.
3236 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3237 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3238 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3240 alloc_table (table, table->rows);
3241 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3242 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3243 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3244 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3247 /* handle interfaces */
3248 if (tb->interfaces) {
3249 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3251 table->rows += mono_array_length (tb->interfaces);
3252 alloc_table (table, table->rows);
3253 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3254 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3255 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3256 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3257 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3258 values += MONO_INTERFACEIMPL_SIZE;
3264 table = &assembly->tables [MONO_TABLE_FIELD];
3265 table->rows += tb->num_fields;
3266 alloc_table (table, table->rows);
3267 for (i = 0; i < tb->num_fields; ++i)
3268 mono_image_get_field_info (
3269 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3272 /* handle constructors */
3274 table = &assembly->tables [MONO_TABLE_METHOD];
3275 table->rows += mono_array_length (tb->ctors);
3276 alloc_table (table, table->rows);
3277 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3278 mono_image_get_ctor_info (domain,
3279 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3282 /* handle methods */
3284 table = &assembly->tables [MONO_TABLE_METHOD];
3285 table->rows += tb->num_methods;
3286 alloc_table (table, table->rows);
3287 for (i = 0; i < tb->num_methods; ++i)
3288 mono_image_get_method_info (
3289 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3292 /* Do the same with properties etc.. */
3293 if (tb->events && mono_array_length (tb->events)) {
3294 table = &assembly->tables [MONO_TABLE_EVENT];
3295 table->rows += mono_array_length (tb->events);
3296 alloc_table (table, table->rows);
3297 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3299 alloc_table (table, table->rows);
3300 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3301 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3302 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3303 for (i = 0; i < mono_array_length (tb->events); ++i)
3304 mono_image_get_event_info (
3305 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3307 if (tb->properties && mono_array_length (tb->properties)) {
3308 table = &assembly->tables [MONO_TABLE_PROPERTY];
3309 table->rows += mono_array_length (tb->properties);
3310 alloc_table (table, table->rows);
3311 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3313 alloc_table (table, table->rows);
3314 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3315 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3316 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3317 for (i = 0; i < mono_array_length (tb->properties); ++i)
3318 mono_image_get_property_info (
3319 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3322 /* handle generic parameters */
3323 if (tb->generic_params) {
3324 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3325 table->rows += mono_array_length (tb->generic_params);
3326 alloc_table (table, table->rows);
3327 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3328 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3330 mono_image_get_generic_param_info (
3331 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3335 mono_image_add_decl_security (assembly,
3336 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3339 MonoDynamicTable *ntable;
3341 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3342 ntable->rows += mono_array_length (tb->subtypes);
3343 alloc_table (ntable, ntable->rows);
3344 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3346 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3347 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3349 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3350 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3351 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3352 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3353 mono_string_to_utf8 (tb->name), tb->table_idx,
3354 ntable->next_idx, ntable->rows);*/
3355 values += MONO_NESTED_CLASS_SIZE;
3362 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3366 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3368 if (!type->subtypes)
3371 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3372 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3373 collect_types (types, subtype);
3378 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3380 if ((*type1)->table_idx < (*type2)->table_idx)
3383 if ((*type1)->table_idx > (*type2)->table_idx)
3390 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3395 for (i = 0; i < mono_array_length (pinfo); ++i) {
3396 MonoReflectionParamBuilder *pb;
3397 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3400 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3405 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3408 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3410 for (i = 0; i < tb->num_fields; ++i) {
3411 MonoReflectionFieldBuilder* fb;
3412 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3413 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3417 for (i = 0; i < mono_array_length (tb->events); ++i) {
3418 MonoReflectionEventBuilder* eb;
3419 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3420 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3423 if (tb->properties) {
3424 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3425 MonoReflectionPropertyBuilder* pb;
3426 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3427 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3431 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3432 MonoReflectionCtorBuilder* cb;
3433 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3434 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3435 params_add_cattrs (assembly, cb->pinfo);
3440 for (i = 0; i < tb->num_methods; ++i) {
3441 MonoReflectionMethodBuilder* mb;
3442 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3443 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3444 params_add_cattrs (assembly, mb->pinfo);
3449 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3450 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3455 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3459 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3461 if (moduleb->global_methods) {
3462 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3463 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3464 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3465 params_add_cattrs (assembly, mb->pinfo);
3469 if (moduleb->global_fields) {
3470 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3471 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3472 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3476 if (moduleb->types) {
3477 for (i = 0; i < moduleb->num_types; ++i)
3478 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3483 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3485 MonoDynamicTable *table;
3489 char *b = blob_size;
3492 table = &assembly->tables [MONO_TABLE_FILE];
3494 alloc_table (table, table->rows);
3495 values = table->values + table->next_idx * MONO_FILE_SIZE;
3496 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3497 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3498 if (module->image->dynamic) {
3499 /* This depends on the fact that the main module is emitted last */
3500 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3501 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3504 path = g_strdup (module->image->name);
3506 mono_sha1_get_digest_from_file (path, hash);
3509 mono_metadata_encode_value (20, b, &b);
3510 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3511 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3516 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3518 MonoDynamicTable *table;
3521 table = &assembly->tables [MONO_TABLE_MODULE];
3522 mb->table_idx = table->next_idx ++;
3523 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3524 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3527 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3528 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3529 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3530 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3534 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3535 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3537 MonoDynamicTable *table;
3541 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3542 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3545 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3547 alloc_table (table, table->rows);
3548 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3550 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3551 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3552 if (klass->nested_in)
3553 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3555 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3556 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3557 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3559 res = table->next_idx;
3563 /* Emit nested types */
3564 if (klass->ext && klass->ext->nested_classes) {
3567 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3568 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3575 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3576 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3581 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3583 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3585 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3586 parent_index, assembly);
3590 * We need to do this ourselves since klass->nested_classes is not set up.
3593 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3594 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3599 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3600 guint32 module_index, MonoDynamicImage *assembly)
3602 MonoImage *image = module->image;
3606 t = &image->tables [MONO_TABLE_TYPEDEF];
3608 for (i = 0; i < t->rows; ++i) {
3609 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3611 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3612 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3617 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3619 MonoDynamicTable *table;
3621 guint32 scope, idx, res, impl;
3622 gboolean forwarder = TRUE;
3624 if (klass->nested_in) {
3625 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3628 scope = resolution_scope_from_image (assembly, klass->image);
3629 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3630 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3631 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3634 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3637 alloc_table (table, table->rows);
3638 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3640 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3641 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3642 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3643 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3644 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3646 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3654 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3659 if (!assemblyb->type_forwarders)
3662 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3663 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3668 type = mono_reflection_type_get_handle (t);
3671 klass = mono_class_from_mono_type (type);
3673 add_exported_type (assemblyb, assembly, klass);
3677 #define align_pointer(base,p)\
3679 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3681 (p) += 4 - (__diff & 3);\
3685 compare_constants (const void *a, const void *b)
3687 const guint32 *a_values = a;
3688 const guint32 *b_values = b;
3689 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3693 compare_semantics (const void *a, const void *b)
3695 const guint32 *a_values = a;
3696 const guint32 *b_values = b;
3697 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3700 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3704 compare_custom_attrs (const void *a, const void *b)
3706 const guint32 *a_values = a;
3707 const guint32 *b_values = b;
3709 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3713 compare_field_marshal (const void *a, const void *b)
3715 const guint32 *a_values = a;
3716 const guint32 *b_values = b;
3718 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3722 compare_nested (const void *a, const void *b)
3724 const guint32 *a_values = a;
3725 const guint32 *b_values = b;
3727 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3731 compare_genericparam (const void *a, const void *b)
3733 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3734 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3736 if ((*b_entry)->owner == (*a_entry)->owner)
3738 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3739 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3741 return (*a_entry)->owner - (*b_entry)->owner;
3745 compare_declsecurity_attrs (const void *a, const void *b)
3747 const guint32 *a_values = a;
3748 const guint32 *b_values = b;
3750 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3754 compare_interface_impl (const void *a, const void *b)
3756 const guint32 *a_values = a;
3757 const guint32 *b_values = b;
3759 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3763 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3767 pad_heap (MonoDynamicStream *sh)
3769 if (sh->index & 3) {
3770 int sz = 4 - (sh->index & 3);
3771 memset (sh->data + sh->index, 0, sz);
3778 MonoDynamicStream *stream;
3782 * build_compressed_metadata() fills in the blob of data that represents the
3783 * raw metadata as it will be saved in the PE file. The five streams are output
3784 * and the metadata tables are comnpressed from the guint32 array representation,
3785 * to the compressed on-disk format.
3788 build_compressed_metadata (MonoDynamicImage *assembly)
3790 MonoDynamicTable *table;
3792 guint64 valid_mask = 0;
3793 guint64 sorted_mask;
3794 guint32 heapt_size = 0;
3795 guint32 meta_size = 256; /* allow for header and other stuff */
3796 guint32 table_offset;
3797 guint32 ntables = 0;
3803 struct StreamDesc stream_desc [5];
3805 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3806 for (i = 0; i < assembly->gen_params->len; i++){
3807 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3808 write_generic_param_entry (assembly, entry);
3811 stream_desc [0].name = "#~";
3812 stream_desc [0].stream = &assembly->tstream;
3813 stream_desc [1].name = "#Strings";
3814 stream_desc [1].stream = &assembly->sheap;
3815 stream_desc [2].name = "#US";
3816 stream_desc [2].stream = &assembly->us;
3817 stream_desc [3].name = "#Blob";
3818 stream_desc [3].stream = &assembly->blob;
3819 stream_desc [4].name = "#GUID";
3820 stream_desc [4].stream = &assembly->guid;
3822 /* tables that are sorted */
3823 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3824 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3825 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3826 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3827 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3828 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3829 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3831 /* Compute table sizes */
3832 /* the MonoImage has already been created in mono_image_basic_init() */
3833 meta = &assembly->image;
3835 /* sizes should be multiple of 4 */
3836 pad_heap (&assembly->blob);
3837 pad_heap (&assembly->guid);
3838 pad_heap (&assembly->sheap);
3839 pad_heap (&assembly->us);
3841 /* Setup the info used by compute_sizes () */
3842 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3843 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3844 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3846 meta_size += assembly->blob.index;
3847 meta_size += assembly->guid.index;
3848 meta_size += assembly->sheap.index;
3849 meta_size += assembly->us.index;
3851 for (i=0; i < MONO_TABLE_NUM; ++i)
3852 meta->tables [i].rows = assembly->tables [i].rows;
3854 for (i = 0; i < MONO_TABLE_NUM; i++){
3855 if (meta->tables [i].rows == 0)
3857 valid_mask |= (guint64)1 << i;
3859 meta->tables [i].row_size = mono_metadata_compute_size (
3860 meta, i, &meta->tables [i].size_bitfield);
3861 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3863 heapt_size += 24; /* #~ header size */
3864 heapt_size += ntables * 4;
3865 /* make multiple of 4 */
3868 meta_size += heapt_size;
3869 meta->raw_metadata = g_malloc0 (meta_size);
3870 p = (unsigned char*)meta->raw_metadata;
3871 /* the metadata signature */
3872 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3873 /* version numbers and 4 bytes reserved */
3874 int16val = (guint16*)p;
3875 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3876 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3878 /* version string */
3879 int32val = (guint32*)p;
3880 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3882 memcpy (p, meta->version, strlen (meta->version));
3883 p += GUINT32_FROM_LE (*int32val);
3884 align_pointer (meta->raw_metadata, p);
3885 int16val = (guint16*)p;
3886 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3887 *int16val = GUINT16_TO_LE (5); /* number of streams */
3891 * write the stream info.
3893 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3894 table_offset += 3; table_offset &= ~3;
3896 assembly->tstream.index = heapt_size;
3897 for (i = 0; i < 5; ++i) {
3898 int32val = (guint32*)p;
3899 stream_desc [i].stream->offset = table_offset;
3900 *int32val++ = GUINT32_TO_LE (table_offset);
3901 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3902 table_offset += GUINT32_FROM_LE (*int32val);
3903 table_offset += 3; table_offset &= ~3;
3905 strcpy ((char*)p, stream_desc [i].name);
3906 p += strlen (stream_desc [i].name) + 1;
3907 align_pointer (meta->raw_metadata, p);
3910 * now copy the data, the table stream header and contents goes first.
3912 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3913 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3914 int32val = (guint32*)p;
3915 *int32val = GUINT32_TO_LE (0); /* reserved */
3918 if (mono_framework_version () > 1) {
3919 *p++ = 2; /* version */
3922 *p++ = 1; /* version */
3926 if (meta->idx_string_wide)
3928 if (meta->idx_guid_wide)
3930 if (meta->idx_blob_wide)
3933 *p++ = 1; /* reserved */
3934 int64val = (guint64*)p;
3935 *int64val++ = GUINT64_TO_LE (valid_mask);
3936 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3938 int32val = (guint32*)p;
3939 for (i = 0; i < MONO_TABLE_NUM; i++){
3940 if (meta->tables [i].rows == 0)
3942 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3944 p = (unsigned char*)int32val;
3946 /* sort the tables that still need sorting */
3947 table = &assembly->tables [MONO_TABLE_CONSTANT];
3949 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3950 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3952 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3953 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3955 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3956 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3958 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3959 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3961 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3962 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3963 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3965 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3966 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3968 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3970 /* compress the tables */
3971 for (i = 0; i < MONO_TABLE_NUM; i++){
3974 guint32 bitfield = meta->tables [i].size_bitfield;
3975 if (!meta->tables [i].rows)
3977 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3978 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3979 meta->tables [i].base = (char*)p;
3980 for (row = 1; row <= meta->tables [i].rows; ++row) {
3981 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3982 for (col = 0; col < assembly->tables [i].columns; ++col) {
3983 switch (mono_metadata_table_size (bitfield, col)) {
3985 *p++ = values [col];
3988 *p++ = values [col] & 0xff;
3989 *p++ = (values [col] >> 8) & 0xff;
3992 *p++ = values [col] & 0xff;
3993 *p++ = (values [col] >> 8) & 0xff;
3994 *p++ = (values [col] >> 16) & 0xff;
3995 *p++ = (values [col] >> 24) & 0xff;
3998 g_assert_not_reached ();
4002 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4005 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4006 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4007 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4008 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4009 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4011 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4015 * Some tables in metadata need to be sorted according to some criteria, but
4016 * when methods and fields are first created with reflection, they may be assigned a token
4017 * that doesn't correspond to the final token they will get assigned after the sorting.
4018 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4019 * with the reflection objects that represent them. Once all the tables are set up, the
4020 * reflection objects will contains the correct table index. fixup_method() will fixup the
4021 * tokens for the method with ILGenerator @ilgen.
4024 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4026 guint32 code_idx = GPOINTER_TO_UINT (value);
4027 MonoReflectionILTokenInfo *iltoken;
4028 MonoReflectionFieldBuilder *field;
4029 MonoReflectionCtorBuilder *ctor;
4030 MonoReflectionMethodBuilder *method;
4031 MonoReflectionTypeBuilder *tb;
4032 MonoReflectionArrayMethod *am;
4034 unsigned char *target;
4036 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4037 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4038 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4039 switch (target [3]) {
4040 case MONO_TABLE_FIELD:
4041 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4042 field = (MonoReflectionFieldBuilder *)iltoken->member;
4043 idx = field->table_idx;
4044 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4045 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4046 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4048 g_assert_not_reached ();
4051 case MONO_TABLE_METHOD:
4052 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4053 method = (MonoReflectionMethodBuilder *)iltoken->member;
4054 idx = method->table_idx;
4055 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4056 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4057 idx = ctor->table_idx;
4058 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4059 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4060 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4061 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4063 g_assert_not_reached ();
4066 case MONO_TABLE_TYPEDEF:
4067 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4068 g_assert_not_reached ();
4069 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4070 idx = tb->table_idx;
4072 case MONO_TABLE_MEMBERREF:
4073 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4074 am = (MonoReflectionArrayMethod*)iltoken->member;
4075 idx = am->table_idx;
4076 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4077 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4078 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4079 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4080 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4081 g_assert (m->klass->generic_class || m->klass->generic_container);
4083 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4085 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4086 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4087 g_assert (is_field_on_inst (f));
4089 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4090 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4092 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4094 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4096 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4099 g_assert_not_reached ();
4102 case MONO_TABLE_METHODSPEC:
4103 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4104 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4105 g_assert (mono_method_signature (m)->generic_param_count);
4107 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4109 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4112 g_assert_not_reached ();
4116 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4118 target [0] = idx & 0xff;
4119 target [1] = (idx >> 8) & 0xff;
4120 target [2] = (idx >> 16) & 0xff;
4127 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4128 * value is not known when the table is emitted.
4131 fixup_cattrs (MonoDynamicImage *assembly)
4133 MonoDynamicTable *table;
4135 guint32 type, i, idx, token;
4138 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4140 for (i = 0; i < table->rows; ++i) {
4141 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4143 type = values [MONO_CUSTOM_ATTR_TYPE];
4144 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4145 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4146 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4147 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4150 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4151 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4152 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4153 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4160 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4162 MonoDynamicTable *table;
4165 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4167 alloc_table (table, table->rows);
4168 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4169 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4170 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4171 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4172 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4177 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4179 MonoDynamicTable *table;
4183 char *b = blob_size;
4185 guint32 idx, offset;
4187 if (rsrc->filename) {
4188 name = mono_string_to_utf8 (rsrc->filename);
4189 sname = g_path_get_basename (name);
4191 table = &assembly->tables [MONO_TABLE_FILE];
4193 alloc_table (table, table->rows);
4194 values = table->values + table->next_idx * MONO_FILE_SIZE;
4195 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4196 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4199 mono_sha1_get_digest_from_file (name, hash);
4200 mono_metadata_encode_value (20, b, &b);
4201 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4202 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4204 idx = table->next_idx++;
4206 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4212 data = mono_array_addr (rsrc->data, char, 0);
4213 len = mono_array_length (rsrc->data);
4219 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4220 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4221 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4222 mono_image_add_stream_data (&assembly->resources, data, len);
4226 * The entry should be emitted into the MANIFESTRESOURCE table of
4227 * the main module, but that needs to reference the FILE table
4228 * which isn't emitted yet.
4235 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4239 set_version_from_string (MonoString *version, guint32 *values)
4241 gchar *ver, *p, *str;
4244 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4245 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4246 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4247 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4250 ver = str = mono_string_to_utf8 (version);
4251 for (i = 0; i < 4; ++i) {
4252 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4258 /* handle Revision and Build */
4268 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4272 char *b = blob_size;
4277 len = mono_array_length (pkey);
4278 mono_metadata_encode_value (len, b, &b);
4279 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4280 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4282 assembly->public_key = g_malloc (len);
4283 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4284 assembly->public_key_len = len;
4286 /* Special case: check for ECMA key (16 bytes) */
4287 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4288 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4289 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4290 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4291 /* minimum key size (in 2.0) is 384 bits */
4292 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4294 /* FIXME - verifier */
4295 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4296 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4298 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4304 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4306 MonoDynamicTable *table;
4307 MonoDynamicImage *assembly;
4308 MonoReflectionAssemblyBuilder *assemblyb;
4312 guint32 module_index;
4314 assemblyb = moduleb->assemblyb;
4315 assembly = moduleb->dynamic_image;
4316 domain = mono_object_domain (assemblyb);
4318 /* Emit ASSEMBLY table */
4319 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4320 alloc_table (table, 1);
4321 values = table->values + MONO_ASSEMBLY_SIZE;
4322 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4323 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4324 if (assemblyb->culture) {
4325 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4327 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4329 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4330 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4331 set_version_from_string (assemblyb->version, values);
4333 /* Emit FILE + EXPORTED_TYPE table */
4335 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4337 MonoReflectionModuleBuilder *file_module =
4338 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4339 if (file_module != moduleb) {
4340 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4342 if (file_module->types) {
4343 for (j = 0; j < file_module->num_types; ++j) {
4344 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4345 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4350 if (assemblyb->loaded_modules) {
4351 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4352 MonoReflectionModule *file_module =
4353 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4354 mono_image_fill_file_table (domain, file_module, assembly);
4356 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4359 if (assemblyb->type_forwarders)
4360 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4362 /* Emit MANIFESTRESOURCE table */
4364 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4366 MonoReflectionModuleBuilder *file_module =
4367 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4368 /* The table for the main module is emitted later */
4369 if (file_module != moduleb) {
4371 if (file_module->resources) {
4372 int len = mono_array_length (file_module->resources);
4373 for (j = 0; j < len; ++j) {
4374 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4375 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4382 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4385 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4386 * for the modulebuilder @moduleb.
4387 * At the end of the process, method and field tokens are fixed up and the
4388 * on-disk compressed metadata representation is created.
4391 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4393 MonoDynamicTable *table;
4394 MonoDynamicImage *assembly;
4395 MonoReflectionAssemblyBuilder *assemblyb;
4401 assemblyb = moduleb->assemblyb;
4402 assembly = moduleb->dynamic_image;
4403 domain = mono_object_domain (assemblyb);
4405 if (assembly->text_rva)
4408 assembly->text_rva = START_TEXT_RVA;
4410 if (moduleb->is_main) {
4411 mono_image_emit_manifest (moduleb);
4414 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4415 table->rows = 1; /* .<Module> */
4417 alloc_table (table, table->rows);
4419 * Set the first entry.
4421 values = table->values + table->columns;
4422 values [MONO_TYPEDEF_FLAGS] = 0;
4423 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4424 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4425 values [MONO_TYPEDEF_EXTENDS] = 0;
4426 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4427 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4430 * handle global methods
4431 * FIXME: test what to do when global methods are defined in multiple modules.
4433 if (moduleb->global_methods) {
4434 table = &assembly->tables [MONO_TABLE_METHOD];
4435 table->rows += mono_array_length (moduleb->global_methods);
4436 alloc_table (table, table->rows);
4437 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4438 mono_image_get_method_info (
4439 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4441 if (moduleb->global_fields) {
4442 table = &assembly->tables [MONO_TABLE_FIELD];
4443 table->rows += mono_array_length (moduleb->global_fields);
4444 alloc_table (table, table->rows);
4445 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4446 mono_image_get_field_info (
4447 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4450 table = &assembly->tables [MONO_TABLE_MODULE];
4451 alloc_table (table, 1);
4452 mono_image_fill_module_table (domain, moduleb, assembly);
4454 /* Collect all types into a list sorted by their table_idx */
4455 types = g_ptr_array_new ();
4458 for (i = 0; i < moduleb->num_types; ++i) {
4459 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4460 collect_types (types, type);
4463 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4464 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4465 table->rows += types->len;
4466 alloc_table (table, table->rows);
4469 * Emit type names + namespaces at one place inside the string heap,
4470 * so load_class_names () needs to touch fewer pages.
4472 for (i = 0; i < types->len; ++i) {
4473 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4474 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4476 for (i = 0; i < types->len; ++i) {
4477 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4478 string_heap_insert_mstring (&assembly->sheap, tb->name);
4481 for (i = 0; i < types->len; ++i) {
4482 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4483 mono_image_get_type_info (domain, type, assembly);
4487 * table->rows is already set above and in mono_image_fill_module_table.
4489 /* add all the custom attributes at the end, once all the indexes are stable */
4490 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4492 /* CAS assembly permissions */
4493 if (assemblyb->permissions_minimum)
4494 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4495 if (assemblyb->permissions_optional)
4496 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4497 if (assemblyb->permissions_refused)
4498 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4500 module_add_cattrs (assembly, moduleb);
4503 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4505 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4506 * the final tokens and don't need another fixup pass. */
4508 if (moduleb->global_methods) {
4509 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4510 MonoReflectionMethodBuilder *mb = mono_array_get (
4511 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4512 mono_image_add_methodimpl (assembly, mb);
4516 for (i = 0; i < types->len; ++i) {
4517 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4518 if (type->methods) {
4519 for (j = 0; j < type->num_methods; ++j) {
4520 MonoReflectionMethodBuilder *mb = mono_array_get (
4521 type->methods, MonoReflectionMethodBuilder*, j);
4523 mono_image_add_methodimpl (assembly, mb);
4528 g_ptr_array_free (types, TRUE);
4530 fixup_cattrs (assembly);
4533 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4536 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4538 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4541 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4545 guint32 import_lookup_table;
4549 guint32 import_address_table_rva;
4557 #ifndef DISABLE_REFLECTION_EMIT
4560 * mono_image_insert_string:
4561 * @module: module builder object
4564 * Insert @str into the user string stream of @module.
4567 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4569 MonoDynamicImage *assembly;
4574 MONO_ARCH_SAVE_REGS;
4576 if (!module->dynamic_image)
4577 mono_image_module_basic_init (module);
4579 assembly = module->dynamic_image;
4581 if (assembly->save) {
4582 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4583 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4584 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4586 char *swapped = g_malloc (2 * mono_string_length (str));
4587 const char *p = (const char*)mono_string_chars (str);
4589 swap_with_size (swapped, p, 2, mono_string_length (str));
4590 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4594 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4596 mono_image_add_stream_data (&assembly->us, "", 1);
4598 idx = assembly->us.index ++;
4601 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4603 return MONO_TOKEN_STRING | idx;
4607 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4612 klass = obj->vtable->klass;
4613 if (strcmp (klass->name, "MonoMethod") == 0) {
4614 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4615 MonoMethodSignature *sig, *old;
4616 guint32 sig_token, parent;
4619 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4621 nargs = mono_array_length (opt_param_types);
4622 old = mono_method_signature (method);
4623 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4625 sig->hasthis = old->hasthis;
4626 sig->explicit_this = old->explicit_this;
4627 sig->call_convention = old->call_convention;
4628 sig->generic_param_count = old->generic_param_count;
4629 sig->param_count = old->param_count + nargs;
4630 sig->sentinelpos = old->param_count;
4631 sig->ret = old->ret;
4633 for (i = 0; i < old->param_count; i++)
4634 sig->params [i] = old->params [i];
4636 for (i = 0; i < nargs; i++) {
4637 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4638 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4641 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4642 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4643 parent >>= MONO_TYPEDEFORREF_BITS;
4645 parent <<= MONO_MEMBERREF_PARENT_BITS;
4646 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4648 sig_token = method_encode_signature (assembly, sig);
4649 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4650 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4651 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4652 ReflectionMethodBuilder rmb;
4653 guint32 parent, sig;
4656 reflection_methodbuilder_from_method_builder (&rmb, mb);
4657 rmb.opt_types = opt_param_types;
4659 sig = method_builder_encode_signature (assembly, &rmb);
4661 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4662 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4664 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4665 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4667 name = mono_string_to_utf8 (rmb.name);
4668 token = mono_image_get_varargs_method_token (
4669 assembly, parent, name, sig);
4672 g_error ("requested method token for %s\n", klass->name);
4679 * mono_image_create_token:
4680 * @assembly: a dynamic assembly
4682 * @register_token: Whenever to register the token in the assembly->tokens hash.
4684 * Get a token to insert in the IL code stream for the given MemberInfo.
4685 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4686 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4690 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4691 gboolean create_methodspec, gboolean register_token)
4696 klass = obj->vtable->klass;
4698 /* Check for user defined reflection objects */
4699 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4700 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4701 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4703 if (strcmp (klass->name, "MethodBuilder") == 0) {
4704 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4705 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4707 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4708 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4710 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4711 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4712 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4713 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4714 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4716 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4717 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4719 token = mono_image_get_ctorbuilder_token (assembly, mb);
4720 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4721 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4722 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4723 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4724 if (tb->generic_params) {
4725 token = mono_image_get_generic_field_token (assembly, fb);
4727 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4729 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4730 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4731 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4732 } else if (strcmp (klass->name, "MonoType") == 0) {
4733 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4734 MonoClass *mc = mono_class_from_mono_type (type);
4735 token = mono_metadata_token_from_dor (
4736 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4737 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4738 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4739 token = mono_metadata_token_from_dor (
4740 mono_image_typedef_or_ref (assembly, type));
4741 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4742 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4743 token = mono_metadata_token_from_dor (
4744 mono_image_typedef_or_ref (assembly, type));
4745 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4746 strcmp (klass->name, "MonoMethod") == 0 ||
4747 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4748 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4749 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4750 if (m->method->is_inflated) {
4751 if (create_methodspec)
4752 token = mono_image_get_methodspec_token (assembly, m->method);
4754 token = mono_image_get_inflated_method_token (assembly, m->method);
4755 } else if ((m->method->klass->image == &assembly->image) &&
4756 !m->method->klass->generic_class) {
4757 static guint32 method_table_idx = 0xffffff;
4758 if (m->method->klass->wastypebuilder) {
4759 /* we use the same token as the one that was assigned
4760 * to the Methodbuilder.
4761 * FIXME: do the equivalent for Fields.
4763 token = m->method->token;
4766 * Each token should have a unique index, but the indexes are
4767 * assigned by managed code, so we don't know about them. An
4768 * easy solution is to count backwards...
4770 method_table_idx --;
4771 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4774 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4776 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4777 } else if (strcmp (klass->name, "MonoField") == 0) {
4778 MonoReflectionField *f = (MonoReflectionField *)obj;
4779 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4780 static guint32 field_table_idx = 0xffffff;
4782 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4784 token = mono_image_get_fieldref_token (assembly, f);
4786 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4787 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4788 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4789 token = mono_image_get_array_token (assembly, m);
4790 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4791 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4792 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4793 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4794 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4795 token = mono_metadata_token_from_dor (
4796 mono_image_typedef_or_ref (assembly, type));
4797 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4798 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4799 token = mono_image_get_field_on_inst_token (assembly, f);
4800 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4801 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4802 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4803 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4804 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4805 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4806 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4807 MonoReflectionType *type = (MonoReflectionType *)obj;
4808 token = mono_metadata_token_from_dor (
4809 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4811 g_error ("requested token for %s\n", klass->name);
4815 mono_image_register_token (assembly, token, obj);
4821 * mono_image_register_token:
4823 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4824 * the Module.ResolveXXXToken () methods to work.
4827 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4829 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4831 /* There could be multiple MethodInfo objects with the same token */
4832 //g_assert (prev == obj);
4834 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4838 static MonoDynamicImage*
4839 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4841 static const guchar entrycode [16] = {0xff, 0x25, 0};
4842 MonoDynamicImage *image;
4845 const char *version;
4847 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4848 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4850 version = mono_get_runtime_info ()->runtime_version;
4853 image = GC_MALLOC (sizeof (MonoDynamicImage));
4855 image = g_new0 (MonoDynamicImage, 1);
4858 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4860 /*g_print ("created image %p\n", image);*/
4861 /* keep in sync with image.c */
4862 image->image.name = assembly_name;
4863 image->image.assembly_name = image->image.name; /* they may be different */
4864 image->image.module_name = module_name;
4865 image->image.version = g_strdup (version);
4866 image->image.md_version_major = 1;
4867 image->image.md_version_minor = 1;
4868 image->image.dynamic = TRUE;
4870 image->image.references = g_new0 (MonoAssembly*, 1);
4871 image->image.references [0] = NULL;
4873 mono_image_init (&image->image);
4875 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4876 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4877 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4878 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4879 image->handleref = g_hash_table_new (NULL, NULL);
4880 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4881 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4882 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4883 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4884 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4885 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4886 image->gen_params = g_ptr_array_new ();
4888 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4889 string_heap_init (&image->sheap);
4890 mono_image_add_stream_data (&image->us, "", 1);
4891 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4892 /* import tables... */
4893 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4894 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4895 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4896 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4897 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4898 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4899 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4900 stream_data_align (&image->code);
4902 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4904 for (i=0; i < MONO_TABLE_NUM; ++i) {
4905 image->tables [i].next_idx = 1;
4906 image->tables [i].columns = table_sizes [i];
4909 image->image.assembly = (MonoAssembly*)assembly;
4910 image->run = assembly->run;
4911 image->save = assembly->save;
4912 image->pe_kind = 0x1; /* ILOnly */
4913 image->machine = 0x14c; /* I386 */
4915 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4922 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4928 mono_dynamic_image_free (MonoDynamicImage *image)
4930 MonoDynamicImage *di = image;
4935 mono_g_hash_table_destroy (di->methodspec);
4937 g_hash_table_destroy (di->typespec);
4939 g_hash_table_destroy (di->typeref);
4941 g_hash_table_destroy (di->handleref);
4943 mono_g_hash_table_destroy (di->tokens);
4944 if (di->generic_def_objects)
4945 mono_g_hash_table_destroy (di->generic_def_objects);
4946 if (di->blob_cache) {
4947 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4948 g_hash_table_destroy (di->blob_cache);
4950 if (di->standalonesig_cache)
4951 g_hash_table_destroy (di->standalonesig_cache);
4952 for (list = di->array_methods; list; list = list->next) {
4953 ArrayMethod *am = (ArrayMethod *)list->data;
4958 g_list_free (di->array_methods);
4959 if (di->gen_params) {
4960 for (i = 0; i < di->gen_params->len; i++) {
4961 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4962 if (entry->gparam->type.type) {
4963 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4964 g_free ((char*)mono_generic_param_info (param)->name);
4967 mono_gc_deregister_root ((char*) &entry->gparam);
4970 g_ptr_array_free (di->gen_params, TRUE);
4972 if (di->token_fixups)
4973 mono_g_hash_table_destroy (di->token_fixups);
4974 if (di->method_to_table_idx)
4975 g_hash_table_destroy (di->method_to_table_idx);
4976 if (di->field_to_table_idx)
4977 g_hash_table_destroy (di->field_to_table_idx);
4978 if (di->method_aux_hash)
4979 g_hash_table_destroy (di->method_aux_hash);
4980 g_free (di->strong_name);
4981 g_free (di->win32_res);
4983 g_free (di->public_key);
4985 /*g_print ("string heap destroy for image %p\n", di);*/
4986 mono_dynamic_stream_reset (&di->sheap);
4987 mono_dynamic_stream_reset (&di->code);
4988 mono_dynamic_stream_reset (&di->resources);
4989 mono_dynamic_stream_reset (&di->us);
4990 mono_dynamic_stream_reset (&di->blob);
4991 mono_dynamic_stream_reset (&di->tstream);
4992 mono_dynamic_stream_reset (&di->guid);
4993 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4994 g_free (di->tables [i].values);
4998 #ifndef DISABLE_REFLECTION_EMIT
5001 * mono_image_basic_init:
5002 * @assembly: an assembly builder object
5004 * Create the MonoImage that represents the assembly builder and setup some
5005 * of the helper hash table and the basic metadata streams.
5008 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5010 MonoDynamicAssembly *assembly;
5011 MonoDynamicImage *image;
5012 MonoDomain *domain = mono_object_domain (assemblyb);
5014 MONO_ARCH_SAVE_REGS;
5016 if (assemblyb->dynamic_assembly)
5020 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5022 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5025 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5027 assembly->assembly.ref_count = 1;
5028 assembly->assembly.dynamic = TRUE;
5029 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5030 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5031 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5032 if (assemblyb->culture)
5033 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5035 assembly->assembly.aname.culture = g_strdup ("");
5037 if (assemblyb->version) {
5038 char *vstr = mono_string_to_utf8 (assemblyb->version);
5039 char **version = g_strsplit (vstr, ".", 4);
5040 char **parts = version;
5041 assembly->assembly.aname.major = atoi (*parts++);
5042 assembly->assembly.aname.minor = atoi (*parts++);
5043 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5044 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5046 g_strfreev (version);
5049 assembly->assembly.aname.major = 0;
5050 assembly->assembly.aname.minor = 0;
5051 assembly->assembly.aname.build = 0;
5052 assembly->assembly.aname.revision = 0;
5055 assembly->run = assemblyb->access != 2;
5056 assembly->save = assemblyb->access != 1;
5058 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5059 image->initial_image = TRUE;
5060 assembly->assembly.aname.name = image->image.name;
5061 assembly->assembly.image = &image->image;
5062 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5063 /* -1 to correct for the trailing NULL byte */
5064 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5065 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5067 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5070 mono_domain_assemblies_lock (domain);
5071 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5072 mono_domain_assemblies_unlock (domain);
5074 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5076 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5078 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5081 #endif /* !DISABLE_REFLECTION_EMIT */
5083 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5086 calc_section_size (MonoDynamicImage *assembly)
5090 /* alignment constraints */
5091 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5092 g_assert ((assembly->code.index % 4) == 0);
5093 assembly->meta_size += 3;
5094 assembly->meta_size &= ~3;
5095 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5096 g_assert ((assembly->resources.index % 4) == 0);
5098 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5099 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5102 if (assembly->win32_res) {
5103 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5105 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5106 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5110 assembly->sections [MONO_SECTION_RELOC].size = 12;
5111 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5121 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5125 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5127 ResTreeNode *t1 = (ResTreeNode*)a;
5128 ResTreeNode *t2 = (ResTreeNode*)b;
5130 return t1->id - t2->id;
5134 * resource_tree_create:
5136 * Organize the resources into a resource tree.
5138 static ResTreeNode *
5139 resource_tree_create (MonoArray *win32_resources)
5141 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5145 tree = g_new0 (ResTreeNode, 1);
5147 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5148 MonoReflectionWin32Resource *win32_res =
5149 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5153 /* FIXME: BUG: this stores managed references in unmanaged memory */
5154 lang_node = g_new0 (ResTreeNode, 1);
5155 lang_node->id = win32_res->lang_id;
5156 lang_node->win32_res = win32_res;
5158 /* Create type node if neccesary */
5160 for (l = tree->children; l; l = l->next)
5161 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5162 type_node = (ResTreeNode*)l->data;
5167 type_node = g_new0 (ResTreeNode, 1);
5168 type_node->id = win32_res->res_type;
5171 * The resource types have to be sorted otherwise
5172 * Windows Explorer can't display the version information.
5174 tree->children = g_slist_insert_sorted (tree->children,
5175 type_node, resource_tree_compare_by_id);
5178 /* Create res node if neccesary */
5180 for (l = type_node->children; l; l = l->next)
5181 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5182 res_node = (ResTreeNode*)l->data;
5187 res_node = g_new0 (ResTreeNode, 1);
5188 res_node->id = win32_res->res_id;
5189 type_node->children = g_slist_append (type_node->children, res_node);
5192 res_node->children = g_slist_append (res_node->children, lang_node);
5199 * resource_tree_encode:
5201 * Encode the resource tree into the format used in the PE file.
5204 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5207 MonoPEResourceDir dir;
5208 MonoPEResourceDirEntry dir_entry;
5209 MonoPEResourceDataEntry data_entry;
5211 guint32 res_id_entries;
5214 * For the format of the resource directory, see the article
5215 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5219 memset (&dir, 0, sizeof (dir));
5220 memset (&dir_entry, 0, sizeof (dir_entry));
5221 memset (&data_entry, 0, sizeof (data_entry));
5223 g_assert (sizeof (dir) == 16);
5224 g_assert (sizeof (dir_entry) == 8);
5225 g_assert (sizeof (data_entry) == 16);
5227 node->offset = p - begin;
5229 /* IMAGE_RESOURCE_DIRECTORY */
5230 res_id_entries = g_slist_length (node->children);
5231 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5233 memcpy (p, &dir, sizeof (dir));
5236 /* Reserve space for entries */
5238 p += sizeof (dir_entry) * res_id_entries;
5240 /* Write children */
5241 for (l = node->children; l; l = l->next) {
5242 ResTreeNode *child = (ResTreeNode*)l->data;
5244 if (child->win32_res) {
5247 child->offset = p - begin;
5249 /* IMAGE_RESOURCE_DATA_ENTRY */
5250 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5251 size = mono_array_length (child->win32_res->res_data);
5252 data_entry.rde_size = GUINT32_TO_LE (size);
5254 memcpy (p, &data_entry, sizeof (data_entry));
5255 p += sizeof (data_entry);
5257 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5260 resource_tree_encode (child, begin, p, &p);
5264 /* IMAGE_RESOURCE_ENTRY */
5265 for (l = node->children; l; l = l->next) {
5266 ResTreeNode *child = (ResTreeNode*)l->data;
5268 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5269 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5271 memcpy (entries, &dir_entry, sizeof (dir_entry));
5272 entries += sizeof (dir_entry);
5279 resource_tree_free (ResTreeNode * node)
5282 for (list = node->children; list; list = list->next)
5283 resource_tree_free ((ResTreeNode*)list->data);
5284 g_slist_free(node->children);
5289 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5294 MonoReflectionWin32Resource *win32_res;
5297 if (!assemblyb->win32_resources)
5301 * Resources are stored in a three level tree inside the PE file.
5302 * - level one contains a node for each type of resource
5303 * - level two contains a node for each resource
5304 * - level three contains a node for each instance of a resource for a
5305 * specific language.
5308 tree = resource_tree_create (assemblyb->win32_resources);
5310 /* Estimate the size of the encoded tree */
5312 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5313 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5314 size += mono_array_length (win32_res->res_data);
5316 /* Directory structure */
5317 size += mono_array_length (assemblyb->win32_resources) * 256;
5318 p = buf = g_malloc (size);
5320 resource_tree_encode (tree, p, p, &p);
5322 g_assert (p - buf <= size);
5324 assembly->win32_res = g_malloc (p - buf);
5325 assembly->win32_res_size = p - buf;
5326 memcpy (assembly->win32_res, buf, p - buf);
5329 resource_tree_free (tree);
5333 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5335 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5338 p += sizeof (MonoPEResourceDir);
5339 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5340 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5341 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5342 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5343 fixup_resource_directory (res_section, child, rva);
5345 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5346 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5349 p += sizeof (MonoPEResourceDirEntry);
5354 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5357 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5358 g_error ("WriteFile returned %d\n", GetLastError ());
5362 * mono_image_create_pefile:
5363 * @mb: a module builder object
5365 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5366 * assembly->pefile where it can be easily retrieved later in chunks.
5369 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5371 MonoMSDOSHeader *msdos;
5372 MonoDotNetHeader *header;
5373 MonoSectionTable *section;
5374 MonoCLIHeader *cli_header;
5375 guint32 size, image_size, virtual_base, text_offset;
5376 guint32 header_start, section_start, file_offset, virtual_offset;
5377 MonoDynamicImage *assembly;
5378 MonoReflectionAssemblyBuilder *assemblyb;
5379 MonoDynamicStream pefile_stream = {0};
5380 MonoDynamicStream *pefile = &pefile_stream;
5382 guint32 *rva, value;
5384 static const unsigned char msheader[] = {
5385 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5386 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5389 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5390 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5391 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5392 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5395 assemblyb = mb->assemblyb;
5397 mono_image_basic_init (assemblyb);
5398 assembly = mb->dynamic_image;
5400 assembly->pe_kind = assemblyb->pe_kind;
5401 assembly->machine = assemblyb->machine;
5402 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5403 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5405 mono_image_build_metadata (mb);
5407 if (mb->is_main && assemblyb->resources) {
5408 int len = mono_array_length (assemblyb->resources);
5409 for (i = 0; i < len; ++i)
5410 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5413 if (mb->resources) {
5414 int len = mono_array_length (mb->resources);
5415 for (i = 0; i < len; ++i)
5416 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5419 build_compressed_metadata (assembly);
5422 assembly_add_win32_resources (assembly, assemblyb);
5424 nsections = calc_section_size (assembly);
5426 /* The DOS header and stub */
5427 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5428 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5430 /* the dotnet header */
5431 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5433 /* the section tables */
5434 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5436 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5437 virtual_offset = VIRT_ALIGN;
5440 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5441 if (!assembly->sections [i].size)
5444 file_offset += FILE_ALIGN - 1;
5445 file_offset &= ~(FILE_ALIGN - 1);
5446 virtual_offset += VIRT_ALIGN - 1;
5447 virtual_offset &= ~(VIRT_ALIGN - 1);
5449 assembly->sections [i].offset = file_offset;
5450 assembly->sections [i].rva = virtual_offset;
5452 file_offset += assembly->sections [i].size;
5453 virtual_offset += assembly->sections [i].size;
5454 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5457 file_offset += FILE_ALIGN - 1;
5458 file_offset &= ~(FILE_ALIGN - 1);
5460 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5462 /* back-patch info */
5463 msdos = (MonoMSDOSHeader*)pefile->data;
5464 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5466 header = (MonoDotNetHeader*)(pefile->data + header_start);
5467 header->pesig [0] = 'P';
5468 header->pesig [1] = 'E';
5470 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5471 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5472 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5473 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5474 if (assemblyb->pekind == 1) {
5476 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5479 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5482 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5484 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5485 header->pe.pe_major = 6;
5486 header->pe.pe_minor = 0;
5487 size = assembly->sections [MONO_SECTION_TEXT].size;
5488 size += FILE_ALIGN - 1;
5489 size &= ~(FILE_ALIGN - 1);
5490 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5491 size = assembly->sections [MONO_SECTION_RSRC].size;
5492 size += FILE_ALIGN - 1;
5493 size &= ~(FILE_ALIGN - 1);
5494 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5495 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5496 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5497 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5498 /* pe_rva_entry_point always at the beginning of the text section */
5499 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5501 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5502 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5503 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5504 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5505 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5506 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5507 size = section_start;
5508 size += FILE_ALIGN - 1;
5509 size &= ~(FILE_ALIGN - 1);
5510 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5512 size += VIRT_ALIGN - 1;
5513 size &= ~(VIRT_ALIGN - 1);
5514 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5517 // Translate the PEFileKind value to the value expected by the Windows loader
5523 // PEFileKinds.Dll == 1
5524 // PEFileKinds.ConsoleApplication == 2
5525 // PEFileKinds.WindowApplication == 3
5528 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5529 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5531 if (assemblyb->pekind == 3)
5536 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5538 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5539 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5540 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5541 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5542 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5543 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5545 /* fill data directory entries */
5547 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5548 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5550 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5551 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5553 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5554 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5555 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5556 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5557 /* patch entrypoint name */
5558 if (assemblyb->pekind == 1)
5559 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5561 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5562 /* patch imported function RVA name */
5563 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5564 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5566 /* the import table */
5567 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5568 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5569 /* patch imported dll RVA name and other entries in the dir */
5570 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5571 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5572 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5573 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5574 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5575 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5577 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5578 value = (assembly->text_rva + assembly->imp_names_offset);
5579 *p++ = (value) & 0xff;
5580 *p++ = (value >> 8) & (0xff);
5581 *p++ = (value >> 16) & (0xff);
5582 *p++ = (value >> 24) & (0xff);
5584 /* the CLI header info */
5585 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5586 cli_header->ch_size = GUINT32_FROM_LE (72);
5587 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5588 if (mono_framework_version () > 1)
5589 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5591 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5592 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5593 if (assemblyb->entry_point) {
5594 guint32 table_idx = 0;
5595 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5596 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5597 table_idx = methodb->table_idx;
5599 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5601 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5603 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5605 /* The embedded managed resources */
5606 text_offset = assembly->text_rva + assembly->code.index;
5607 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5608 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5609 text_offset += assembly->resources.index;
5610 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5611 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5612 text_offset += assembly->meta_size;
5613 if (assembly->strong_name_size) {
5614 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5615 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5616 text_offset += assembly->strong_name_size;
5619 /* write the section tables and section content */
5620 section = (MonoSectionTable*)(pefile->data + section_start);
5621 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5622 static const char section_names [][7] = {
5623 ".text", ".rsrc", ".reloc"
5625 if (!assembly->sections [i].size)
5627 strcpy (section->st_name, section_names [i]);
5628 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5629 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5630 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5631 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5632 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5633 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5634 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5638 checked_write_file (file, pefile->data, pefile->index);
5640 mono_dynamic_stream_reset (pefile);
5642 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5643 if (!assembly->sections [i].size)
5646 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5647 g_error ("SetFilePointer returned %d\n", GetLastError ());
5650 case MONO_SECTION_TEXT:
5651 /* patch entry point */
5652 p = (guchar*)(assembly->code.data + 2);
5653 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5654 *p++ = (value) & 0xff;
5655 *p++ = (value >> 8) & 0xff;
5656 *p++ = (value >> 16) & 0xff;
5657 *p++ = (value >> 24) & 0xff;
5659 checked_write_file (file, assembly->code.data, assembly->code.index);
5660 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5661 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5662 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5665 g_free (assembly->image.raw_metadata);
5667 case MONO_SECTION_RELOC: {
5671 guint16 type_and_offset;
5675 g_assert (sizeof (reloc) == 12);
5677 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5678 reloc.block_size = GUINT32_FROM_LE (12);
5681 * the entrypoint is always at the start of the text section
5682 * 3 is IMAGE_REL_BASED_HIGHLOW
5683 * 2 is patch_size_rva - text_rva
5685 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5688 checked_write_file (file, &reloc, sizeof (reloc));
5692 case MONO_SECTION_RSRC:
5693 if (assembly->win32_res) {
5695 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5696 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5697 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5701 g_assert_not_reached ();
5705 /* check that the file is properly padded */
5706 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5707 g_error ("SetFilePointer returned %d\n", GetLastError ());
5708 if (! SetEndOfFile (file))
5709 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5711 mono_dynamic_stream_reset (&assembly->code);
5712 mono_dynamic_stream_reset (&assembly->us);
5713 mono_dynamic_stream_reset (&assembly->blob);
5714 mono_dynamic_stream_reset (&assembly->guid);
5715 mono_dynamic_stream_reset (&assembly->sheap);
5717 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5718 g_hash_table_destroy (assembly->blob_cache);
5719 assembly->blob_cache = NULL;
5722 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5725 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5727 g_assert_not_reached ();
5730 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5732 #ifndef DISABLE_REFLECTION_EMIT
5734 MonoReflectionModule *
5735 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5739 MonoImageOpenStatus status;
5740 MonoDynamicAssembly *assembly;
5741 guint32 module_count;
5742 MonoImage **new_modules;
5743 gboolean *new_modules_loaded;
5745 name = mono_string_to_utf8 (fileName);
5747 image = mono_image_open (name, &status);
5750 if (status == MONO_IMAGE_ERROR_ERRNO)
5751 exc = mono_get_exception_file_not_found (fileName);
5753 exc = mono_get_exception_bad_image_format (name);
5755 mono_raise_exception (exc);
5760 assembly = ab->dynamic_assembly;
5761 image->assembly = (MonoAssembly*)assembly;
5763 module_count = image->assembly->image->module_count;
5764 new_modules = g_new0 (MonoImage *, module_count + 1);
5765 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5767 if (image->assembly->image->modules)
5768 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5769 if (image->assembly->image->modules_loaded)
5770 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5771 new_modules [module_count] = image;
5772 new_modules_loaded [module_count] = TRUE;
5773 mono_image_addref (image);
5775 g_free (image->assembly->image->modules);
5776 image->assembly->image->modules = new_modules;
5777 image->assembly->image->modules_loaded = new_modules_loaded;
5778 image->assembly->image->module_count ++;
5780 mono_assembly_load_references (image, &status);
5782 mono_image_close (image);
5783 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5786 return mono_module_get_object (mono_domain_get (), image);
5789 #endif /* DISABLE_REFLECTION_EMIT */
5792 * We need to return always the same object for MethodInfo, FieldInfo etc..
5793 * but we need to consider the reflected type.
5794 * type uses a different hash, since it uses custom hash/equal functions.
5799 MonoClass *refclass;
5803 reflected_equal (gconstpointer a, gconstpointer b) {
5804 const ReflectedEntry *ea = a;
5805 const ReflectedEntry *eb = b;
5807 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5811 reflected_hash (gconstpointer a) {
5812 const ReflectedEntry *ea = a;
5813 return mono_aligned_addr_hash (ea->item);
5816 #define CHECK_OBJECT(t,p,k) \
5822 mono_domain_lock (domain); \
5823 if (!domain->refobject_hash) \
5824 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5825 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5826 mono_domain_unlock (domain); \
5829 mono_domain_unlock (domain); \
5832 #ifdef HAVE_BOEHM_GC
5833 /* ReflectedEntry doesn't need to be GC tracked */
5834 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5835 #define FREE_REFENTRY(entry) g_free ((entry))
5836 #define REFENTRY_REQUIRES_CLEANUP
5838 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5840 #define FREE_REFENTRY(entry)
5843 #define CACHE_OBJECT(t,p,o,k) \
5846 ReflectedEntry pe; \
5848 pe.refclass = (k); \
5849 mono_domain_lock (domain); \
5850 if (!domain->refobject_hash) \
5851 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5852 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5854 ReflectedEntry *e = ALLOC_REFENTRY; \
5856 e->refclass = (k); \
5857 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5860 mono_domain_unlock (domain); \
5865 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5867 mono_domain_lock (domain);
5868 if (domain->refobject_hash) {
5870 gpointer orig_pe, orig_value;
5873 pe.refclass = klass;
5874 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5875 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5876 FREE_REFENTRY (orig_pe);
5879 mono_domain_unlock (domain);
5882 #ifdef REFENTRY_REQUIRES_CLEANUP
5884 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5886 FREE_REFENTRY (key);
5891 mono_reflection_cleanup_domain (MonoDomain *domain)
5893 if (domain->refobject_hash) {
5894 /*let's avoid scanning the whole hashtable if not needed*/
5895 #ifdef REFENTRY_REQUIRES_CLEANUP
5896 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5898 mono_g_hash_table_destroy (domain->refobject_hash);
5899 domain->refobject_hash = NULL;
5903 #ifndef DISABLE_REFLECTION_EMIT
5905 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5907 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5911 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5913 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5917 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5919 MonoDynamicImage *image = moduleb->dynamic_image;
5920 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5924 MonoImage **new_modules;
5926 char *name, *fqname;
5928 * FIXME: we already created an image in mono_image_basic_init (), but
5929 * we don't know which module it belongs to, since that is only
5930 * determined at assembly save time.
5932 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5933 name = mono_string_to_utf8 (ab->name);
5934 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
5935 if (!mono_error_ok (&error)) {
5937 mono_error_raise_exception (&error);
5939 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
5941 moduleb->module.image = &image->image;
5942 moduleb->dynamic_image = image;
5943 register_module (mono_object_domain (moduleb), moduleb, image);
5945 /* register the module with the assembly */
5946 ass = ab->dynamic_assembly->assembly.image;
5947 module_count = ass->module_count;
5948 new_modules = g_new0 (MonoImage *, module_count + 1);
5951 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5952 new_modules [module_count] = &image->image;
5953 mono_image_addref (&image->image);
5955 g_free (ass->modules);
5956 ass->modules = new_modules;
5957 ass->module_count ++;
5962 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
5964 MonoDynamicImage *image = moduleb->dynamic_image;
5966 g_assert (type->type);
5967 image->wrappers_type = mono_class_from_mono_type (type->type);
5973 * mono_assembly_get_object:
5974 * @domain: an app domain
5975 * @assembly: an assembly
5977 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5979 MonoReflectionAssembly*
5980 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5982 static MonoClass *System_Reflection_Assembly;
5983 MonoReflectionAssembly *res;
5985 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5986 if (!System_Reflection_Assembly)
5987 System_Reflection_Assembly = mono_class_from_name (
5988 mono_defaults.corlib, "System.Reflection", "Assembly");
5989 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5990 res->assembly = assembly;
5992 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5997 MonoReflectionModule*
5998 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6000 static MonoClass *System_Reflection_Module;
6001 MonoReflectionModule *res;
6004 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6005 if (!System_Reflection_Module)
6006 System_Reflection_Module = mono_class_from_name (
6007 mono_defaults.corlib, "System.Reflection", "Module");
6008 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6011 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6013 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6014 basename = g_path_get_basename (image->name);
6015 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6016 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6020 if (image->assembly->image == image) {
6021 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6025 if (image->assembly->image->modules) {
6026 for (i = 0; i < image->assembly->image->module_count; i++) {
6027 if (image->assembly->image->modules [i] == image)
6028 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6030 g_assert (res->token);
6034 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6037 MonoReflectionModule*
6038 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6040 static MonoClass *System_Reflection_Module;
6041 MonoReflectionModule *res;
6042 MonoTableInfo *table;
6043 guint32 cols [MONO_FILE_SIZE];
6045 guint32 i, name_idx;
6048 if (!System_Reflection_Module)
6049 System_Reflection_Module = mono_class_from_name (
6050 mono_defaults.corlib, "System.Reflection", "Module");
6051 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6053 table = &image->tables [MONO_TABLE_FILE];
6054 g_assert (table_index < table->rows);
6055 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6058 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6059 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6061 /* Check whenever the row has a corresponding row in the moduleref table */
6062 table = &image->tables [MONO_TABLE_MODULEREF];
6063 for (i = 0; i < table->rows; ++i) {
6064 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6065 val = mono_metadata_string_heap (image, name_idx);
6066 if (strcmp (val, name) == 0)
6067 res->image = image->modules [i];
6070 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6071 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6072 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6073 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6074 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6080 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6082 if ((t1->type != t2->type) ||
6083 (t1->byref != t2->byref))
6087 case MONO_TYPE_VOID:
6088 case MONO_TYPE_BOOLEAN:
6089 case MONO_TYPE_CHAR:
6100 case MONO_TYPE_STRING:
6103 case MONO_TYPE_OBJECT:
6104 case MONO_TYPE_TYPEDBYREF:
6106 case MONO_TYPE_VALUETYPE:
6107 case MONO_TYPE_CLASS:
6108 case MONO_TYPE_SZARRAY:
6109 return t1->data.klass == t2->data.klass;
6111 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6112 case MONO_TYPE_ARRAY:
6113 if (t1->data.array->rank != t2->data.array->rank)
6115 return t1->data.array->eklass == t2->data.array->eklass;
6116 case MONO_TYPE_GENERICINST: {
6118 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6119 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6120 if (i1->type_argc != i2->type_argc)
6122 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6123 &t2->data.generic_class->container_class->byval_arg))
6125 /* FIXME: we should probably just compare the instance pointers directly. */
6126 for (i = 0; i < i1->type_argc; ++i) {
6127 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6133 case MONO_TYPE_MVAR:
6134 return t1->data.generic_param == t2->data.generic_param;
6136 g_error ("implement type compare for %0x!", t1->type);
6144 mymono_metadata_type_hash (MonoType *t1)
6150 hash |= t1->byref << 6; /* do not collide with t1->type values */
6152 case MONO_TYPE_VALUETYPE:
6153 case MONO_TYPE_CLASS:
6154 case MONO_TYPE_SZARRAY:
6155 /* check if the distribution is good enough */
6156 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6158 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6159 case MONO_TYPE_GENERICINST: {
6161 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6162 hash += g_str_hash (t1->data.generic_class->container_class->name);
6164 for (i = 0; i < inst->type_argc; ++i) {
6165 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6174 static MonoReflectionGenericClass*
6175 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6177 static MonoClass *System_Reflection_MonoGenericClass;
6178 MonoReflectionGenericClass *res;
6179 MonoClass *klass, *gklass;
6180 MonoGenericInst *ginst;
6181 MonoArray *type_args;
6184 if (!System_Reflection_MonoGenericClass) {
6185 System_Reflection_MonoGenericClass = mono_class_from_name (
6186 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6187 g_assert (System_Reflection_MonoGenericClass);
6190 klass = mono_class_from_mono_type (geninst);
6191 gklass = klass->generic_class->container_class;
6193 mono_class_init (klass);
6196 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6198 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6201 res->type.type = geninst;
6202 g_assert (gklass->reflection_info);
6203 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6204 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6206 ginst = klass->generic_class->context.class_inst;
6207 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6208 for (i = 0; i < ginst->type_argc; ++i)
6209 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6210 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6216 verify_safe_for_managed_space (MonoType *type)
6218 switch (type->type) {
6220 case MONO_TYPE_ARRAY:
6221 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6223 return verify_safe_for_managed_space (type->data.type);
6224 case MONO_TYPE_SZARRAY:
6225 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6226 case MONO_TYPE_GENERICINST: {
6227 MonoGenericInst *inst = type->data.generic_class->inst;
6231 for (i = 0; i < inst->type_argc; ++i)
6232 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6238 case MONO_TYPE_MVAR:
6245 * mono_type_get_object:
6246 * @domain: an app domain
6249 * Return an System.MonoType object representing the type @type.
6252 mono_type_get_object (MonoDomain *domain, MonoType *type)
6254 MonoReflectionType *res;
6255 MonoClass *klass = mono_class_from_mono_type (type);
6257 /*we must avoid using @type as it might have come
6258 * from a mono_metadata_type_dup and the caller
6259 * expects that is can be freed.
6260 * Using the right type from
6262 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6264 /* void is very common */
6265 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6266 return (MonoReflectionType*)domain->typeof_void;
6269 * If the vtable of the given class was already created, we can use
6270 * the MonoType from there and avoid all locking and hash table lookups.
6272 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6273 * that the resulting object is different.
6275 if (type == &klass->byval_arg && !klass->image->dynamic) {
6276 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6277 if (vtable && vtable->type)
6278 return vtable->type;
6281 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6282 mono_domain_lock (domain);
6283 if (!domain->type_hash)
6284 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6285 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6286 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6287 mono_domain_unlock (domain);
6288 mono_loader_unlock ();
6291 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6292 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6293 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6294 mono_g_hash_table_insert (domain->type_hash, type, res);
6295 mono_domain_unlock (domain);
6296 mono_loader_unlock ();
6300 if (!verify_safe_for_managed_space (type)) {
6301 mono_domain_unlock (domain);
6302 mono_loader_unlock ();
6303 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6306 if (klass->reflection_info && !klass->wastypebuilder) {
6307 /* g_assert_not_reached (); */
6308 /* should this be considered an error condition? */
6310 mono_domain_unlock (domain);
6311 mono_loader_unlock ();
6312 return klass->reflection_info;
6315 // FIXME: Get rid of this, do it in the icalls for Type
6316 mono_class_init (klass);
6318 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6320 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6323 mono_g_hash_table_insert (domain->type_hash, type, res);
6325 if (type->type == MONO_TYPE_VOID)
6326 domain->typeof_void = (MonoObject*)res;
6328 mono_domain_unlock (domain);
6329 mono_loader_unlock ();
6334 * mono_method_get_object:
6335 * @domain: an app domain
6337 * @refclass: the reflected type (can be NULL)
6339 * Return an System.Reflection.MonoMethod object representing the method @method.
6341 MonoReflectionMethod*
6342 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6345 * We use the same C representation for methods and constructors, but the type
6346 * name in C# is different.
6348 static MonoClass *System_Reflection_MonoMethod = NULL;
6349 static MonoClass *System_Reflection_MonoCMethod = NULL;
6350 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6351 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6353 MonoReflectionMethod *ret;
6355 if (method->is_inflated) {
6356 MonoReflectionGenericMethod *gret;
6358 refclass = method->klass;
6359 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6360 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6361 if (!System_Reflection_MonoGenericCMethod)
6362 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6363 klass = System_Reflection_MonoGenericCMethod;
6365 if (!System_Reflection_MonoGenericMethod)
6366 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6367 klass = System_Reflection_MonoGenericMethod;
6369 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6370 gret->method.method = method;
6371 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6372 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6373 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6377 refclass = method->klass;
6379 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6380 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6381 if (!System_Reflection_MonoCMethod)
6382 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6383 klass = System_Reflection_MonoCMethod;
6386 if (!System_Reflection_MonoMethod)
6387 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6388 klass = System_Reflection_MonoMethod;
6390 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6391 ret->method = method;
6392 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6393 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6397 * mono_method_clear_object:
6399 * Clear the cached reflection objects for the dynamic method METHOD.
6402 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6405 g_assert (method->dynamic);
6407 klass = method->klass;
6409 clear_cached_object (domain, method, klass);
6410 klass = klass->parent;
6412 /* Added by mono_param_get_objects () */
6413 clear_cached_object (domain, &(method->signature), NULL);
6414 klass = method->klass;
6416 clear_cached_object (domain, &(method->signature), klass);
6417 klass = klass->parent;
6422 * mono_field_get_object:
6423 * @domain: an app domain
6427 * Return an System.Reflection.MonoField object representing the field @field
6430 MonoReflectionField*
6431 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6433 MonoReflectionField *res;
6434 static MonoClass *monofield_klass;
6436 CHECK_OBJECT (MonoReflectionField *, field, klass);
6437 if (!monofield_klass)
6438 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6439 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6442 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6443 if (is_field_on_inst (field))
6444 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6446 res->attrs = field->type->attrs;
6447 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6448 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6452 * mono_property_get_object:
6453 * @domain: an app domain
6455 * @property: a property
6457 * Return an System.Reflection.MonoProperty object representing the property @property
6460 MonoReflectionProperty*
6461 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6463 MonoReflectionProperty *res;
6464 static MonoClass *monoproperty_klass;
6466 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6467 if (!monoproperty_klass)
6468 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6469 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6471 res->property = property;
6472 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6476 * mono_event_get_object:
6477 * @domain: an app domain
6481 * Return an System.Reflection.MonoEvent object representing the event @event
6484 MonoReflectionEvent*
6485 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6487 MonoReflectionEvent *res;
6488 MonoReflectionMonoEvent *mono_event;
6489 static MonoClass *monoevent_klass;
6491 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6492 if (!monoevent_klass)
6493 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6494 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6495 mono_event->klass = klass;
6496 mono_event->event = event;
6497 res = (MonoReflectionEvent*)mono_event;
6498 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6502 * mono_get_reflection_missing_object:
6503 * @domain: Domain where the object lives
6505 * Returns the System.Reflection.Missing.Value singleton object
6506 * (of type System.Reflection.Missing).
6508 * Used as the value for ParameterInfo.DefaultValue when Optional
6512 mono_get_reflection_missing_object (MonoDomain *domain)
6515 static MonoClassField *missing_value_field = NULL;
6517 if (!missing_value_field) {
6518 MonoClass *missing_klass;
6519 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6520 mono_class_init (missing_klass);
6521 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6522 g_assert (missing_value_field);
6524 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6530 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6533 *dbnull = mono_get_dbnull_object (domain);
6538 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6540 if (!*reflection_missing)
6541 *reflection_missing = mono_get_reflection_missing_object (domain);
6542 return *reflection_missing;
6546 * mono_param_get_objects:
6547 * @domain: an app domain
6550 * Return an System.Reflection.ParameterInfo array object representing the parameters
6551 * in the method @method.
6554 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6556 static MonoClass *System_Reflection_ParameterInfo;
6557 static MonoClass *System_Reflection_ParameterInfo_array;
6558 MonoArray *res = NULL;
6559 MonoReflectionMethod *member = NULL;
6560 MonoReflectionParameter *param = NULL;
6561 char **names, **blobs = NULL;
6562 guint32 *types = NULL;
6563 MonoType *type = NULL;
6564 MonoObject *dbnull = NULL;
6565 MonoObject *missing = NULL;
6566 MonoMarshalSpec **mspecs;
6567 MonoMethodSignature *sig;
6568 MonoVTable *pinfo_vtable;
6571 if (!System_Reflection_ParameterInfo_array) {
6574 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6575 mono_memory_barrier ();
6576 System_Reflection_ParameterInfo = klass;
6578 klass = mono_array_class_get (klass, 1);
6579 mono_memory_barrier ();
6580 System_Reflection_ParameterInfo_array = klass;
6583 if (!mono_method_signature (method)->param_count)
6584 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6586 /* Note: the cache is based on the address of the signature into the method
6587 * since we already cache MethodInfos with the method as keys.
6589 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6591 sig = mono_method_signature (method);
6592 member = mono_method_get_object (domain, method, refclass);
6593 names = g_new (char *, sig->param_count);
6594 mono_method_get_param_names (method, (const char **) names);
6596 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6597 mono_method_get_marshal_info (method, mspecs);
6599 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6600 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6601 for (i = 0; i < sig->param_count; ++i) {
6602 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6603 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6604 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6605 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6606 param->PositionImpl = i;
6607 param->AttrsImpl = sig->params [i]->attrs;
6609 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6610 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6611 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6613 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6617 blobs = g_new0 (char *, sig->param_count);
6618 types = g_new0 (guint32, sig->param_count);
6619 get_default_param_value_blobs (method, blobs, types);
6622 /* Build MonoType for the type from the Constant Table */
6624 type = g_new0 (MonoType, 1);
6625 type->type = types [i];
6626 type->data.klass = NULL;
6627 if (types [i] == MONO_TYPE_CLASS)
6628 type->data.klass = mono_defaults.object_class;
6629 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6630 /* For enums, types [i] contains the base type */
6632 type->type = MONO_TYPE_VALUETYPE;
6633 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6635 type->data.klass = mono_class_from_mono_type (type);
6637 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6639 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6640 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6641 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6642 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6644 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6650 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6652 mono_array_setref (res, i, param);
6659 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6661 mono_metadata_free_marshal_spec (mspecs [i]);
6664 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6668 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6670 return mono_param_get_objects_internal (domain, method, NULL);
6674 * mono_method_body_get_object:
6675 * @domain: an app domain
6678 * Return an System.Reflection.MethodBody object representing the method @method.
6680 MonoReflectionMethodBody*
6681 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6683 static MonoClass *System_Reflection_MethodBody = NULL;
6684 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6685 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6686 MonoReflectionMethodBody *ret;
6687 MonoMethodNormal *mn;
6688 MonoMethodHeader *header;
6689 guint32 method_rva, local_var_sig_token;
6691 unsigned char format, flags;
6694 if (!System_Reflection_MethodBody)
6695 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6696 if (!System_Reflection_LocalVariableInfo)
6697 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6698 if (!System_Reflection_ExceptionHandlingClause)
6699 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6701 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6703 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6704 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6705 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6706 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6708 mn = (MonoMethodNormal *)method;
6709 header = mono_method_get_header (method);
6711 /* Obtain local vars signature token */
6712 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6713 ptr = mono_image_rva_map (method->klass->image, method_rva);
6714 flags = *(const unsigned char *) ptr;
6715 format = flags & METHOD_HEADER_FORMAT_MASK;
6717 case METHOD_HEADER_TINY_FORMAT:
6718 local_var_sig_token = 0;
6720 case METHOD_HEADER_FAT_FORMAT:
6724 local_var_sig_token = read32 (ptr);
6727 g_assert_not_reached ();
6730 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6732 ret->init_locals = header->init_locals;
6733 ret->max_stack = header->max_stack;
6734 ret->local_var_sig_token = local_var_sig_token;
6735 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6736 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6739 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6740 for (i = 0; i < header->num_locals; ++i) {
6741 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6742 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6743 info->is_pinned = header->locals [i]->pinned;
6744 info->local_index = i;
6745 mono_array_setref (ret->locals, i, info);
6749 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6750 for (i = 0; i < header->num_clauses; ++i) {
6751 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6752 MonoExceptionClause *clause = &header->clauses [i];
6754 info->flags = clause->flags;
6755 info->try_offset = clause->try_offset;
6756 info->try_length = clause->try_len;
6757 info->handler_offset = clause->handler_offset;
6758 info->handler_length = clause->handler_len;
6759 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6760 info->filter_offset = clause->data.filter_offset;
6761 else if (clause->data.catch_class)
6762 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6764 mono_array_setref (ret->clauses, i, info);
6767 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6772 * mono_get_dbnull_object:
6773 * @domain: Domain where the object lives
6775 * Returns the System.DBNull.Value singleton object
6777 * Used as the value for ParameterInfo.DefaultValue
6780 mono_get_dbnull_object (MonoDomain *domain)
6783 static MonoClassField *dbnull_value_field = NULL;
6785 if (!dbnull_value_field) {
6786 MonoClass *dbnull_klass;
6787 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6788 mono_class_init (dbnull_klass);
6789 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6790 g_assert (dbnull_value_field);
6792 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6798 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6800 guint32 param_index, i, lastp, crow = 0;
6801 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6804 MonoClass *klass = method->klass;
6805 MonoImage *image = klass->image;
6806 MonoMethodSignature *methodsig = mono_method_signature (method);
6808 MonoTableInfo *constt;
6809 MonoTableInfo *methodt;
6810 MonoTableInfo *paramt;
6812 if (!methodsig->param_count)
6815 mono_class_init (klass);
6817 if (klass->image->dynamic) {
6818 MonoReflectionMethodAux *aux;
6819 if (method->is_inflated)
6820 method = ((MonoMethodInflated*)method)->declaring;
6821 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6822 if (aux && aux->param_defaults) {
6823 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6824 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6829 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6830 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6831 constt = &image->tables [MONO_TABLE_CONSTANT];
6833 idx = mono_method_get_index (method) - 1;
6834 g_assert (idx != -1);
6836 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6837 if (idx + 1 < methodt->rows)
6838 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6840 lastp = paramt->rows + 1;
6842 for (i = param_index; i < lastp; ++i) {
6845 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6846 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6848 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6851 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6856 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6857 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6858 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6865 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6870 MonoType *basetype = type;
6875 klass = mono_class_from_mono_type (type);
6876 if (klass->valuetype) {
6877 object = mono_object_new (domain, klass);
6878 retval = ((gchar *) object + sizeof (MonoObject));
6879 if (klass->enumtype)
6880 basetype = mono_class_enum_basetype (klass);
6885 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6892 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6896 memset (assembly, 0, sizeof (MonoAssemblyName));
6898 assembly->culture = "";
6899 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6901 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6904 while (g_ascii_isspace (*p) || *p == ',') {
6913 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6915 assembly->major = strtoul (p, &s, 10);
6916 if (s == p || *s != '.')
6919 assembly->minor = strtoul (p, &s, 10);
6920 if (s == p || *s != '.')
6923 assembly->build = strtoul (p, &s, 10);
6924 if (s == p || *s != '.')
6927 assembly->revision = strtoul (p, &s, 10);
6931 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6933 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6934 assembly->culture = "";
6937 assembly->culture = p;
6938 while (*p && *p != ',') {
6942 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6944 if (strncmp (p, "null", 4) == 0) {
6949 while (*p && *p != ',') {
6952 len = (p - start + 1);
6953 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6954 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6955 g_strlcpy ((char*)assembly->public_key_token, start, len);
6958 while (*p && *p != ',')
6962 while (g_ascii_isspace (*p) || *p == ',') {
6976 * mono_reflection_parse_type:
6979 * Parse a type name as accepted by the GetType () method and output the info
6980 * extracted in the info structure.
6981 * the name param will be mangled, so, make a copy before passing it to this function.
6982 * The fields in info will be valid until the memory pointed to by name is valid.
6984 * See also mono_type_get_name () below.
6986 * Returns: 0 on parse error.
6989 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6990 MonoTypeNameParse *info)
6992 char *start, *p, *w, *temp, *last_point, *startn;
6993 int in_modifiers = 0;
6994 int isbyref = 0, rank, arity = 0, i;
6996 start = p = w = name;
6998 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6999 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7000 info->name = info->name_space = NULL;
7001 info->nested = NULL;
7002 info->modifiers = NULL;
7003 info->type_arguments = NULL;
7005 /* last_point separates the namespace from the name */
7008 while (*p == ' ') p++, start++, w++, name++;
7013 *p = 0; /* NULL terminate the name */
7015 info->nested = g_list_append (info->nested, startn);
7016 /* we have parsed the nesting namespace + name */
7020 info->name_space = start;
7022 info->name = last_point + 1;
7024 info->name_space = (char *)"";
7043 i = strtol (p, &temp, 10);
7060 info->name_space = start;
7062 info->name = last_point + 1;
7064 info->name_space = (char *)"";
7071 if (isbyref) /* only one level allowed by the spec */
7074 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7078 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7084 info->type_arguments = g_ptr_array_new ();
7085 for (i = 0; i < arity; i++) {
7086 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7087 gboolean fqname = FALSE;
7089 g_ptr_array_add (info->type_arguments, subinfo);
7096 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7107 while (*p && (*p != ']'))
7115 if (g_ascii_isspace (*aname)) {
7122 !assembly_name_to_aname (&subinfo->assembly, aname))
7126 if (i + 1 < arity) {
7146 else if (*p == '*') /* '*' means unknown lower bound */
7147 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7154 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7165 if (g_ascii_isspace (*p)) {
7172 return 0; /* missing assembly name */
7173 if (!assembly_name_to_aname (&info->assembly, p))
7179 if (info->assembly.name)
7182 // *w = 0; /* terminate class name */
7184 if (!info->name || !*info->name)
7188 /* add other consistency checks */
7193 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7195 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7199 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7201 gboolean type_resolve = FALSE;
7203 MonoImage *rootimage = image;
7205 if (info->assembly.name) {
7206 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7207 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7209 * This could happen in the AOT compiler case when the search hook is not
7212 assembly = image->assembly;
7214 /* then we must load the assembly ourselve - see #60439 */
7215 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7219 image = assembly->image;
7220 } else if (!image) {
7221 image = mono_defaults.corlib;
7224 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7225 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7226 image = mono_defaults.corlib;
7227 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7234 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7239 gboolean bounded = FALSE;
7242 image = mono_defaults.corlib;
7245 klass = mono_class_from_name_case (image, info->name_space, info->name);
7247 klass = mono_class_from_name (image, info->name_space, info->name);
7250 for (mod = info->nested; mod; mod = mod->next) {
7251 gpointer iter = NULL;
7255 mono_class_init (parent);
7257 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7259 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7262 if (strcmp (klass->name, mod->data) == 0)
7271 mono_class_init (klass);
7273 if (info->type_arguments) {
7274 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7275 MonoReflectionType *the_type;
7279 for (i = 0; i < info->type_arguments->len; i++) {
7280 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7282 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7283 if (!type_args [i]) {
7289 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7291 instance = mono_reflection_bind_generic_parameters (
7292 the_type, info->type_arguments->len, type_args);
7298 klass = mono_class_from_mono_type (instance);
7301 for (mod = info->modifiers; mod; mod = mod->next) {
7302 modval = GPOINTER_TO_UINT (mod->data);
7303 if (!modval) { /* byref: must be last modifier */
7304 return &klass->this_arg;
7305 } else if (modval == -1) {
7306 klass = mono_ptr_class_get (&klass->byval_arg);
7307 } else if (modval == -2) {
7309 } else { /* array rank */
7310 klass = mono_bounded_array_class_get (klass, modval, bounded);
7312 mono_class_init (klass);
7315 return &klass->byval_arg;
7319 * mono_reflection_get_type:
7320 * @image: a metadata context
7321 * @info: type description structure
7322 * @ignorecase: flag for case-insensitive string compares
7323 * @type_resolve: whenever type resolve was already tried
7325 * Build a MonoType from the type description in @info.
7330 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7331 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7335 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7337 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7341 g_assert (assembly->dynamic);
7343 /* Enumerate all modules */
7346 if (abuilder->modules) {
7347 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7348 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7349 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7355 if (!type && abuilder->loaded_modules) {
7356 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7357 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7358 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7368 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7371 MonoReflectionAssembly *assembly;
7375 if (image && image->dynamic)
7376 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7378 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7381 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7388 *type_resolve = TRUE;
7391 /* Reconstruct the type name */
7392 fullName = g_string_new ("");
7393 if (info->name_space && (info->name_space [0] != '\0'))
7394 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7396 g_string_printf (fullName, "%s", info->name);
7397 for (mod = info->nested; mod; mod = mod->next)
7398 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7400 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7402 if (assembly->assembly->dynamic)
7403 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7405 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7408 g_string_free (fullName, TRUE);
7413 mono_reflection_free_type_info (MonoTypeNameParse *info)
7415 g_list_free (info->modifiers);
7416 g_list_free (info->nested);
7418 if (info->type_arguments) {
7421 for (i = 0; i < info->type_arguments->len; i++) {
7422 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7424 mono_reflection_free_type_info (subinfo);
7425 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7429 g_ptr_array_free (info->type_arguments, TRUE);
7434 * mono_reflection_type_from_name:
7436 * @image: a metadata context (can be NULL).
7438 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7439 * it defaults to get the type from @image or, if @image is NULL or loading
7440 * from it fails, uses corlib.
7444 mono_reflection_type_from_name (char *name, MonoImage *image)
7446 MonoType *type = NULL;
7447 MonoTypeNameParse info;
7450 /* Make a copy since parse_type modifies its argument */
7451 tmp = g_strdup (name);
7453 /*g_print ("requested type %s\n", str);*/
7454 if (mono_reflection_parse_type (tmp, &info)) {
7455 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7459 mono_reflection_free_type_info (&info);
7464 * mono_reflection_get_token:
7466 * Return the metadata token of OBJ which should be an object
7467 * representing a metadata element.
7470 mono_reflection_get_token (MonoObject *obj)
7475 klass = obj->vtable->klass;
7477 if (strcmp (klass->name, "MethodBuilder") == 0) {
7478 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7480 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7481 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7482 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7484 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7485 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7486 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7488 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7489 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7490 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7491 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7492 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7493 } else if (strcmp (klass->name, "MonoType") == 0) {
7494 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7495 token = mono_class_from_mono_type (type)->type_token;
7496 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7497 strcmp (klass->name, "MonoMethod") == 0 ||
7498 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7499 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7500 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7501 if (m->method->is_inflated) {
7502 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7503 return inflated->declaring->token;
7505 token = m->method->token;
7507 } else if (strcmp (klass->name, "MonoField") == 0) {
7508 MonoReflectionField *f = (MonoReflectionField*)obj;
7510 if (is_field_on_inst (f->field)) {
7511 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7512 int field_index = f->field - dgclass->fields;
7515 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7516 obj = dgclass->field_objects [field_index];
7517 return mono_reflection_get_token (obj);
7519 token = mono_class_get_field_token (f->field);
7520 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7521 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7523 token = mono_class_get_property_token (p->property);
7524 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7525 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7527 token = mono_class_get_event_token (p->event);
7528 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7529 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7531 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7532 } else if (strcmp (klass->name, "Module") == 0) {
7533 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7536 } else if (strcmp (klass->name, "Assembly") == 0) {
7537 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7539 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7540 MonoException *ex = mono_get_exception_not_implemented (msg);
7542 mono_raise_exception (ex);
7549 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7551 int slen, type = t->type;
7552 MonoClass *tklass = t->data.klass;
7558 case MONO_TYPE_BOOLEAN: {
7559 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7564 case MONO_TYPE_CHAR:
7566 case MONO_TYPE_I2: {
7567 guint16 *val = g_malloc (sizeof (guint16));
7572 #if SIZEOF_VOID_P == 4
7578 case MONO_TYPE_I4: {
7579 guint32 *val = g_malloc (sizeof (guint32));
7584 #if SIZEOF_VOID_P == 8
7585 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7589 case MONO_TYPE_I8: {
7590 guint64 *val = g_malloc (sizeof (guint64));
7595 case MONO_TYPE_R8: {
7596 double *val = g_malloc (sizeof (double));
7601 case MONO_TYPE_VALUETYPE:
7602 if (t->data.klass->enumtype) {
7603 type = mono_class_enum_basetype (t->data.klass)->type;
7606 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7609 case MONO_TYPE_STRING:
7610 if (*p == (char)0xFF) {
7614 slen = mono_metadata_decode_value (p, &p);
7616 return mono_string_new_len (mono_domain_get (), p, slen);
7617 case MONO_TYPE_CLASS: {
7620 if (*p == (char)0xFF) {
7625 slen = mono_metadata_decode_value (p, &p);
7626 n = g_memdup (p, slen + 1);
7628 t = mono_reflection_type_from_name (n, image);
7630 g_warning ("Cannot load type '%s'", n);
7634 return mono_type_get_object (mono_domain_get (), t);
7638 case MONO_TYPE_OBJECT: {
7641 MonoClass *subc = NULL;
7646 } else if (subt == 0x0E) {
7647 type = MONO_TYPE_STRING;
7649 } else if (subt == 0x1D) {
7650 MonoType simple_type = {{0}};
7655 /* See Partition II, Appendix B3 */
7656 etype = MONO_TYPE_OBJECT;
7657 type = MONO_TYPE_SZARRAY;
7658 simple_type.type = etype;
7659 tklass = mono_class_from_mono_type (&simple_type);
7661 } else if (subt == 0x55) {
7664 slen = mono_metadata_decode_value (p, &p);
7665 n = g_memdup (p, slen + 1);
7667 t = mono_reflection_type_from_name (n, image);
7669 g_error ("Cannot load type '%s'", n);
7672 subc = mono_class_from_mono_type (t);
7673 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7674 MonoType simple_type = {{0}};
7675 simple_type.type = subt;
7676 subc = mono_class_from_mono_type (&simple_type);
7678 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7680 val = load_cattr_value (image, &subc->byval_arg, p, end);
7681 obj = mono_object_new (mono_domain_get (), subc);
7682 g_assert (!subc->has_references);
7683 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7687 case MONO_TYPE_SZARRAY: {
7689 guint32 i, alen, basetype;
7692 if (alen == 0xffffffff) {
7696 arr = mono_array_new (mono_domain_get(), tklass, alen);
7697 basetype = tklass->byval_arg.type;
7698 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7699 basetype = mono_class_enum_basetype (tklass)->type;
7704 case MONO_TYPE_BOOLEAN:
7705 for (i = 0; i < alen; i++) {
7706 MonoBoolean val = *p++;
7707 mono_array_set (arr, MonoBoolean, i, val);
7710 case MONO_TYPE_CHAR:
7713 for (i = 0; i < alen; i++) {
7714 guint16 val = read16 (p);
7715 mono_array_set (arr, guint16, i, val);
7722 for (i = 0; i < alen; i++) {
7723 guint32 val = read32 (p);
7724 mono_array_set (arr, guint32, i, val);
7729 for (i = 0; i < alen; i++) {
7732 mono_array_set (arr, double, i, val);
7738 for (i = 0; i < alen; i++) {
7739 guint64 val = read64 (p);
7740 mono_array_set (arr, guint64, i, val);
7744 case MONO_TYPE_CLASS:
7745 case MONO_TYPE_OBJECT:
7746 case MONO_TYPE_STRING:
7747 for (i = 0; i < alen; i++) {
7748 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7749 mono_array_setref (arr, i, item);
7753 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7759 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7765 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7767 static MonoClass *klass;
7768 static MonoMethod *ctor;
7770 void *params [2], *unboxed;
7773 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7775 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7777 params [0] = mono_type_get_object (mono_domain_get (), t);
7779 retval = mono_object_new (mono_domain_get (), klass);
7780 unboxed = mono_object_unbox (retval);
7781 mono_runtime_invoke (ctor, unboxed, params, NULL);
7787 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7789 static MonoClass *klass;
7790 static MonoMethod *ctor;
7792 void *unboxed, *params [2];
7795 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7797 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7800 params [1] = typedarg;
7801 retval = mono_object_new (mono_domain_get (), klass);
7802 unboxed = mono_object_unbox (retval);
7803 mono_runtime_invoke (ctor, unboxed, params, NULL);
7809 type_is_reference (MonoType *type)
7811 switch (type->type) {
7812 case MONO_TYPE_BOOLEAN:
7813 case MONO_TYPE_CHAR:
7826 case MONO_TYPE_VALUETYPE:
7834 free_param_data (MonoMethodSignature *sig, void **params) {
7836 for (i = 0; i < sig->param_count; ++i) {
7837 if (!type_is_reference (sig->params [i]))
7838 g_free (params [i]);
7843 * Find the field index in the metadata FieldDef table.
7846 find_field_index (MonoClass *klass, MonoClassField *field) {
7849 for (i = 0; i < klass->field.count; ++i) {
7850 if (field == &klass->fields [i])
7851 return klass->field.first + 1 + i;
7857 * Find the property index in the metadata Property table.
7860 find_property_index (MonoClass *klass, MonoProperty *property) {
7863 for (i = 0; i < klass->ext->property.count; ++i) {
7864 if (property == &klass->ext->properties [i])
7865 return klass->ext->property.first + 1 + i;
7871 * Find the event index in the metadata Event table.
7874 find_event_index (MonoClass *klass, MonoEvent *event) {
7877 for (i = 0; i < klass->ext->event.count; ++i) {
7878 if (event == &klass->ext->events [i])
7879 return klass->ext->event.first + 1 + i;
7885 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7887 const char *p = (const char*)data;
7889 guint32 i, j, num_named;
7891 void *params_buf [32];
7893 MonoMethodSignature *sig;
7895 mono_class_init (method->klass);
7898 attr = mono_object_new (mono_domain_get (), method->klass);
7899 mono_runtime_invoke (method, attr, NULL, NULL);
7903 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7906 /*g_print ("got attr %s\n", method->klass->name);*/
7908 sig = mono_method_signature (method);
7909 if (sig->param_count < 32)
7910 params = params_buf;
7912 /* Allocate using GC so it gets GC tracking */
7913 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7917 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7918 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7922 attr = mono_object_new (mono_domain_get (), method->klass);
7923 mono_runtime_invoke (method, attr, params, NULL);
7924 free_param_data (method->signature, params);
7925 num_named = read16 (named);
7927 for (j = 0; j < num_named; j++) {
7929 char *name, named_type, data_type;
7930 named_type = *named++;
7931 data_type = *named++; /* type of data */
7932 if (data_type == MONO_TYPE_SZARRAY)
7933 data_type = *named++;
7934 if (data_type == MONO_TYPE_ENUM) {
7937 type_len = mono_metadata_decode_blob_size (named, &named);
7938 type_name = g_malloc (type_len + 1);
7939 memcpy (type_name, named, type_len);
7940 type_name [type_len] = 0;
7942 /* FIXME: lookup the type and check type consistency */
7945 name_len = mono_metadata_decode_blob_size (named, &named);
7946 name = g_malloc (name_len + 1);
7947 memcpy (name, named, name_len);
7948 name [name_len] = 0;
7950 if (named_type == 0x53) {
7951 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7952 void *val = load_cattr_value (image, field->type, named, &named);
7953 mono_field_set_value (attr, field, val);
7954 if (!type_is_reference (field->type))
7956 } else if (named_type == 0x54) {
7959 MonoType *prop_type;
7961 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7962 /* can we have more that 1 arg in a custom attr named property? */
7963 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7964 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7965 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7966 mono_property_set_value (prop, attr, pparams, NULL);
7967 if (!type_is_reference (prop_type))
7968 g_free (pparams [0]);
7973 if (params != params_buf)
7974 mono_gc_free_fixed (params);
7980 * mono_reflection_create_custom_attr_data_args:
7982 * Create an array of typed and named arguments from the cattr blob given by DATA.
7983 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
7984 * NAMED_ARG_INFO will contain information about the named arguments.
7987 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)
7989 MonoArray *typedargs, *namedargs;
7990 MonoClass *attrklass;
7992 const char *p = (const char*)data;
7994 guint32 i, j, num_named;
7995 CattrNamedArg *arginfo = NULL;
7997 mono_class_init (method->klass);
8001 *named_arg_info = NULL;
8003 domain = mono_domain_get ();
8005 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8008 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8012 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8016 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8017 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8018 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8019 mono_array_setref (typedargs, i, obj);
8021 if (!type_is_reference (mono_method_signature (method)->params [i]))
8026 num_named = read16 (named);
8027 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8029 attrklass = method->klass;
8031 arginfo = g_new0 (CattrNamedArg, num_named);
8032 *named_arg_info = arginfo;
8034 for (j = 0; j < num_named; j++) {
8036 char *name, named_type, data_type;
8037 named_type = *named++;
8038 data_type = *named++; /* type of data */
8039 if (data_type == MONO_TYPE_SZARRAY)
8040 data_type = *named++;
8041 if (data_type == MONO_TYPE_ENUM) {
8044 type_len = mono_metadata_decode_blob_size (named, &named);
8045 type_name = g_malloc (type_len + 1);
8046 memcpy (type_name, named, type_len);
8047 type_name [type_len] = 0;
8049 /* FIXME: lookup the type and check type consistency */
8052 name_len = mono_metadata_decode_blob_size (named, &named);
8053 name = g_malloc (name_len + 1);
8054 memcpy (name, named, name_len);
8055 name [name_len] = 0;
8057 if (named_type == 0x53) {
8059 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8062 arginfo [j].type = field->type;
8063 arginfo [j].field = field;
8065 val = load_cattr_value (image, field->type, named, &named);
8066 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8067 mono_array_setref (namedargs, j, obj);
8068 if (!type_is_reference (field->type))
8070 } else if (named_type == 0x54) {
8072 MonoType *prop_type;
8073 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8076 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8077 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8079 arginfo [j].type = prop_type;
8080 arginfo [j].prop = prop;
8082 val = load_cattr_value (image, prop_type, named, &named);
8083 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8084 mono_array_setref (namedargs, j, obj);
8085 if (!type_is_reference (prop_type))
8091 *typed_args = typedargs;
8092 *named_args = namedargs;
8096 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8098 MonoArray *typedargs, *namedargs;
8099 static MonoMethod *ctor;
8103 CattrNamedArg *arginfo;
8106 mono_class_init (method->klass);
8109 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8111 domain = mono_domain_get ();
8113 /* This is for Attributes with no parameters */
8114 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8115 params [0] = mono_method_get_object (domain, method, NULL);
8116 params [1] = params [2] = NULL;
8117 mono_runtime_invoke (method, attr, params, NULL);
8121 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8122 if (!typedargs || !namedargs)
8125 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8126 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8127 MonoObject *typedarg;
8129 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8130 mono_array_setref (typedargs, i, typedarg);
8133 for (i = 0; i < mono_array_length (namedargs); ++i) {
8134 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8135 MonoObject *typedarg, *namedarg, *minfo;
8137 if (arginfo [i].prop)
8138 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8140 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8142 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8143 namedarg = create_cattr_named_arg (minfo, typedarg);
8145 mono_array_setref (namedargs, i, namedarg);
8148 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8149 params [0] = mono_method_get_object (domain, method, NULL);
8150 params [1] = typedargs;
8151 params [2] = namedargs;
8152 mono_runtime_invoke (ctor, attr, params, NULL);
8157 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8163 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8164 for (i = 0; i < cinfo->num_attrs; ++i) {
8165 if (!cinfo->attrs [i].ctor)
8166 /* The cattr type is not finished yet */
8167 /* We should include the type name but cinfo doesn't contain it */
8168 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8169 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8170 mono_array_setref (result, i, attr);
8176 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8183 for (i = 0; i < cinfo->num_attrs; ++i) {
8184 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8188 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8190 for (i = 0; i < cinfo->num_attrs; ++i) {
8191 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8192 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8193 mono_array_setref (result, n, attr);
8201 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8207 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8208 for (i = 0; i < cinfo->num_attrs; ++i) {
8209 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8210 mono_array_setref (result, i, attr);
8216 * mono_custom_attrs_from_index:
8218 * Returns: NULL if no attributes are found or if a loading error occurs.
8221 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8223 guint32 mtoken, i, len;
8224 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8226 MonoCustomAttrInfo *ainfo;
8227 GList *tmp, *list = NULL;
8230 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8232 i = mono_metadata_custom_attrs_from_index (image, idx);
8236 while (i < ca->rows) {
8237 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8239 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8242 len = g_list_length (list);
8245 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8246 ainfo->num_attrs = len;
8247 ainfo->image = image;
8248 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8249 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8250 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8251 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8252 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8253 mtoken |= MONO_TOKEN_METHOD_DEF;
8255 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8256 mtoken |= MONO_TOKEN_MEMBER_REF;
8259 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8262 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8263 if (!ainfo->attrs [i].ctor) {
8264 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8269 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8270 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8271 ainfo->attrs [i].data = (guchar*)data;
8279 mono_custom_attrs_from_method (MonoMethod *method)
8284 * An instantiated method has the same cattrs as the generic method definition.
8286 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8287 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8289 if (method->is_inflated)
8290 method = ((MonoMethodInflated *) method)->declaring;
8292 if (method->dynamic || method->klass->image->dynamic)
8293 return lookup_custom_attr (method->klass->image, method);
8296 /* Synthetic methods */
8299 idx = mono_method_get_index (method);
8300 idx <<= MONO_CUSTOM_ATTR_BITS;
8301 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8302 return mono_custom_attrs_from_index (method->klass->image, idx);
8306 mono_custom_attrs_from_class (MonoClass *klass)
8310 if (klass->generic_class)
8311 klass = klass->generic_class->container_class;
8313 if (klass->image->dynamic)
8314 return lookup_custom_attr (klass->image, klass);
8316 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8317 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8318 idx <<= MONO_CUSTOM_ATTR_BITS;
8319 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8321 idx = mono_metadata_token_index (klass->type_token);
8322 idx <<= MONO_CUSTOM_ATTR_BITS;
8323 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8325 return mono_custom_attrs_from_index (klass->image, idx);
8329 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8333 if (assembly->image->dynamic)
8334 return lookup_custom_attr (assembly->image, assembly);
8335 idx = 1; /* there is only one assembly */
8336 idx <<= MONO_CUSTOM_ATTR_BITS;
8337 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8338 return mono_custom_attrs_from_index (assembly->image, idx);
8341 static MonoCustomAttrInfo*
8342 mono_custom_attrs_from_module (MonoImage *image)
8347 return lookup_custom_attr (image, image);
8348 idx = 1; /* there is only one module */
8349 idx <<= MONO_CUSTOM_ATTR_BITS;
8350 idx |= MONO_CUSTOM_ATTR_MODULE;
8351 return mono_custom_attrs_from_index (image, idx);
8355 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8359 if (klass->image->dynamic) {
8360 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8361 return lookup_custom_attr (klass->image, property);
8363 idx = find_property_index (klass, property);
8364 idx <<= MONO_CUSTOM_ATTR_BITS;
8365 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8366 return mono_custom_attrs_from_index (klass->image, idx);
8370 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8374 if (klass->image->dynamic) {
8375 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8376 return lookup_custom_attr (klass->image, event);
8378 idx = find_event_index (klass, event);
8379 idx <<= MONO_CUSTOM_ATTR_BITS;
8380 idx |= MONO_CUSTOM_ATTR_EVENT;
8381 return mono_custom_attrs_from_index (klass->image, idx);
8385 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8388 if (klass->image->dynamic) {
8389 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8390 return lookup_custom_attr (klass->image, field);
8392 idx = find_field_index (klass, field);
8393 idx <<= MONO_CUSTOM_ATTR_BITS;
8394 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8395 return mono_custom_attrs_from_index (klass->image, idx);
8399 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8402 guint32 i, idx, method_index;
8403 guint32 param_list, param_last, param_pos, found;
8405 MonoReflectionMethodAux *aux;
8408 * An instantiated method has the same cattrs as the generic method definition.
8410 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8411 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8413 if (method->is_inflated)
8414 method = ((MonoMethodInflated *) method)->declaring;
8416 if (method->klass->image->dynamic) {
8417 MonoCustomAttrInfo *res, *ainfo;
8420 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8421 if (!aux || !aux->param_cattr)
8424 /* Need to copy since it will be freed later */
8425 ainfo = aux->param_cattr [param];
8426 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8427 res = g_malloc0 (size);
8428 memcpy (res, ainfo, size);
8432 image = method->klass->image;
8433 method_index = mono_method_get_index (method);
8434 ca = &image->tables [MONO_TABLE_METHOD];
8436 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8437 if (method_index == ca->rows) {
8438 ca = &image->tables [MONO_TABLE_PARAM];
8439 param_last = ca->rows + 1;
8441 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8442 ca = &image->tables [MONO_TABLE_PARAM];
8445 for (i = param_list; i < param_last; ++i) {
8446 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8447 if (param_pos == param) {
8455 idx <<= MONO_CUSTOM_ATTR_BITS;
8456 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8457 return mono_custom_attrs_from_index (image, idx);
8461 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8465 for (i = 0; i < ainfo->num_attrs; ++i) {
8466 klass = ainfo->attrs [i].ctor->klass;
8467 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8474 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8481 for (i = 0; i < ainfo->num_attrs; ++i) {
8482 klass = ainfo->attrs [i].ctor->klass;
8483 if (mono_class_has_parent (klass, attr_klass)) {
8488 if (attr_index == -1)
8491 attrs = mono_custom_attrs_construct (ainfo);
8493 return mono_array_get (attrs, MonoObject*, attr_index);
8499 * mono_reflection_get_custom_attrs_info:
8500 * @obj: a reflection object handle
8502 * Return the custom attribute info for attributes defined for the
8503 * reflection handle @obj. The objects.
8505 * FIXME this function leaks like a sieve for SRE objects.
8508 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8511 MonoCustomAttrInfo *cinfo = NULL;
8513 klass = obj->vtable->klass;
8514 if (klass == mono_defaults.monotype_class) {
8515 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8516 klass = mono_class_from_mono_type (type);
8517 cinfo = mono_custom_attrs_from_class (klass);
8518 } else if (strcmp ("Assembly", klass->name) == 0) {
8519 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8520 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8521 } else if (strcmp ("Module", klass->name) == 0) {
8522 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8523 cinfo = mono_custom_attrs_from_module (module->image);
8524 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8525 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8526 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8527 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8528 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8529 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8530 } else if (strcmp ("MonoField", klass->name) == 0) {
8531 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8532 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8533 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8534 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8535 cinfo = mono_custom_attrs_from_method (rmethod->method);
8536 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8537 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8538 cinfo = mono_custom_attrs_from_method (rmethod->method);
8539 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8540 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8541 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8542 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8543 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8544 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8545 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8546 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8547 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8548 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8549 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8550 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8551 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8552 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8553 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8554 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8555 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8556 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8557 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8558 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8559 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8560 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8561 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8562 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8563 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8564 } else { /* handle other types here... */
8565 g_error ("get custom attrs not yet supported for %s", klass->name);
8572 * mono_reflection_get_custom_attrs_by_type:
8573 * @obj: a reflection object handle
8575 * Return an array with all the custom attributes defined of the
8576 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8577 * of that type are returned. The objects are fully build. Return NULL if a loading error
8581 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8584 MonoCustomAttrInfo *cinfo;
8586 cinfo = mono_reflection_get_custom_attrs_info (obj);
8589 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8591 result = mono_custom_attrs_construct (cinfo);
8593 mono_custom_attrs_free (cinfo);
8595 if (mono_loader_get_last_error ())
8597 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8604 * mono_reflection_get_custom_attrs:
8605 * @obj: a reflection object handle
8607 * Return an array with all the custom attributes defined of the
8608 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8612 mono_reflection_get_custom_attrs (MonoObject *obj)
8614 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8618 * mono_reflection_get_custom_attrs_data:
8619 * @obj: a reflection obj handle
8621 * Returns an array of System.Reflection.CustomAttributeData,
8622 * which include information about attributes reflected on
8623 * types loaded using the Reflection Only methods
8626 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8629 MonoCustomAttrInfo *cinfo;
8631 cinfo = mono_reflection_get_custom_attrs_info (obj);
8633 result = mono_custom_attrs_data_construct (cinfo);
8635 mono_custom_attrs_free (cinfo);
8637 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8642 static MonoReflectionType*
8643 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8645 static MonoMethod *method_get_underlying_system_type = NULL;
8646 MonoMethod *usertype_method;
8648 if (!method_get_underlying_system_type)
8649 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8650 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8651 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8654 #ifndef DISABLE_REFLECTION_EMIT
8657 is_corlib_type (MonoClass *class)
8659 return class->image == mono_defaults.corlib;
8663 is_usertype (MonoReflectionType *ref)
8665 MonoClass *class = mono_object_class (ref);
8666 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
8669 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8670 static MonoClass *cached_class; \
8672 return cached_class == _class; \
8673 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8674 cached_class = _class; \
8681 is_sre_array (MonoClass *class)
8683 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8687 is_sre_byref (MonoClass *class)
8689 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8693 is_sre_pointer (MonoClass *class)
8695 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8699 is_sre_generic_instance (MonoClass *class)
8701 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8705 mono_reflection_type_get_handle (MonoReflectionType* ref)
8713 if (is_usertype (ref)) {
8714 ref = mono_reflection_type_get_underlying_system_type (ref);
8715 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8720 class = mono_object_class (ref);
8722 if (is_sre_array (class)) {
8724 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8725 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8727 if (sre_array->rank == 0) //single dimentional array
8728 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8730 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8731 sre_array->type.type = res;
8733 } else if (is_sre_byref (class)) {
8735 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8736 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8738 res = &mono_class_from_mono_type (base)->this_arg;
8739 sre_byref->type.type = res;
8741 } else if (is_sre_pointer (class)) {
8743 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8744 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8746 res = &mono_ptr_class_get (base)->byval_arg;
8747 sre_pointer->type.type = res;
8749 } else if (is_sre_generic_instance (class)) {
8750 MonoType *res, **types;
8751 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8754 count = mono_array_length (gclass->type_arguments);
8755 types = g_new0 (MonoType*, count);
8756 for (i = 0; i < count; ++i) {
8757 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8758 types [i] = mono_reflection_type_get_handle (t);
8761 res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
8764 gclass->type.type = res;
8768 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8772 static MonoReflectionType*
8773 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
8775 if (!type || type->type)
8778 if (is_usertype (type)) {
8779 type = mono_reflection_type_get_underlying_system_type (type);
8780 if (is_usertype (type))
8781 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8788 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8790 mono_reflection_type_get_handle (type);
8794 * LOCKING: Assumes the loader lock is held.
8796 static MonoMethodSignature*
8797 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8798 MonoMethodSignature *sig;
8801 count = parameters? mono_array_length (parameters): 0;
8803 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8804 sig->param_count = count;
8805 sig->sentinelpos = -1; /* FIXME */
8806 for (i = 0; i < count; ++i)
8807 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8812 * LOCKING: Assumes the loader lock is held.
8814 static MonoMethodSignature*
8815 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8816 MonoMethodSignature *sig;
8818 sig = parameters_to_signature (image, ctor->parameters);
8819 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8820 sig->ret = &mono_defaults.void_class->byval_arg;
8825 * LOCKING: Assumes the loader lock is held.
8827 static MonoMethodSignature*
8828 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8829 MonoMethodSignature *sig;
8831 sig = parameters_to_signature (image, method->parameters);
8832 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8833 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8834 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8838 static MonoMethodSignature*
8839 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8840 MonoMethodSignature *sig;
8842 sig = parameters_to_signature (NULL, method->parameters);
8843 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8844 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8845 sig->generic_param_count = 0;
8850 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8852 MonoClass *klass = mono_object_class (prop);
8853 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8854 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8855 *name = mono_string_to_utf8 (pb->name);
8856 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8858 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8859 *name = g_strdup (p->property->name);
8860 if (p->property->get)
8861 *type = mono_method_signature (p->property->get)->ret;
8863 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8868 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8870 MonoClass *klass = mono_object_class (field);
8871 if (strcmp (klass->name, "FieldBuilder") == 0) {
8872 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8873 *name = mono_string_to_utf8 (fb->name);
8874 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8876 MonoReflectionField *f = (MonoReflectionField *)field;
8877 *name = g_strdup (mono_field_get_name (f->field));
8878 *type = f->field->type;
8881 #endif /* !DISABLE_REFLECTION_EMIT */
8884 * Encode a value in a custom attribute stream of bytes.
8885 * The value to encode is either supplied as an object in argument val
8886 * (valuetypes are boxed), or as a pointer to the data in the
8888 * @type represents the type of the value
8889 * @buffer is the start of the buffer
8890 * @p the current position in the buffer
8891 * @buflen contains the size of the buffer and is used to return the new buffer size
8892 * if this needs to be realloced.
8893 * @retbuffer and @retp return the start and the position of the buffer
8896 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8898 MonoTypeEnum simple_type;
8900 if ((p-buffer) + 10 >= *buflen) {
8903 newbuf = g_realloc (buffer, *buflen);
8904 p = newbuf + (p-buffer);
8908 argval = ((char*)arg + sizeof (MonoObject));
8909 simple_type = type->type;
8911 switch (simple_type) {
8912 case MONO_TYPE_BOOLEAN:
8917 case MONO_TYPE_CHAR:
8920 swap_with_size (p, argval, 2, 1);
8926 swap_with_size (p, argval, 4, 1);
8930 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8940 swap_with_size (p, argval, 8, 1);
8946 swap_with_size (p, argval, 8, 1);
8949 case MONO_TYPE_VALUETYPE:
8950 if (type->data.klass->enumtype) {
8951 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8954 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8957 case MONO_TYPE_STRING: {
8964 str = mono_string_to_utf8 ((MonoString*)arg);
8965 slen = strlen (str);
8966 if ((p-buffer) + 10 + slen >= *buflen) {
8970 newbuf = g_realloc (buffer, *buflen);
8971 p = newbuf + (p-buffer);
8974 mono_metadata_encode_value (slen, p, &p);
8975 memcpy (p, str, slen);
8980 case MONO_TYPE_CLASS: {
8988 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
8989 slen = strlen (str);
8990 if ((p-buffer) + 10 + slen >= *buflen) {
8994 newbuf = g_realloc (buffer, *buflen);
8995 p = newbuf + (p-buffer);
8998 mono_metadata_encode_value (slen, p, &p);
8999 memcpy (p, str, slen);
9004 case MONO_TYPE_SZARRAY: {
9006 MonoClass *eclass, *arg_eclass;
9009 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9012 len = mono_array_length ((MonoArray*)arg);
9014 *p++ = (len >> 8) & 0xff;
9015 *p++ = (len >> 16) & 0xff;
9016 *p++ = (len >> 24) & 0xff;
9018 *retbuffer = buffer;
9019 eclass = type->data.klass;
9020 arg_eclass = mono_object_class (arg)->element_class;
9023 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9024 eclass = mono_defaults.object_class;
9026 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9027 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9028 int elsize = mono_class_array_element_size (arg_eclass);
9029 for (i = 0; i < len; ++i) {
9030 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9033 } else if (eclass->valuetype && arg_eclass->valuetype) {
9034 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9035 int elsize = mono_class_array_element_size (eclass);
9036 for (i = 0; i < len; ++i) {
9037 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9041 for (i = 0; i < len; ++i) {
9042 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9047 case MONO_TYPE_OBJECT: {
9053 * The parameter type is 'object' but the type of the actual
9054 * argument is not. So we have to add type information to the blob
9055 * too. This is completely undocumented in the spec.
9059 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9064 klass = mono_object_class (arg);
9066 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9069 } else if (klass->enumtype) {
9071 } else if (klass == mono_defaults.string_class) {
9072 simple_type = MONO_TYPE_STRING;
9075 } else if (klass->rank == 1) {
9077 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9078 /* See Partition II, Appendix B3 */
9081 *p++ = klass->element_class->byval_arg.type;
9082 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9084 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9085 *p++ = simple_type = klass->byval_arg.type;
9088 g_error ("unhandled type in custom attr");
9090 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9091 slen = strlen (str);
9092 if ((p-buffer) + 10 + slen >= *buflen) {
9096 newbuf = g_realloc (buffer, *buflen);
9097 p = newbuf + (p-buffer);
9100 mono_metadata_encode_value (slen, p, &p);
9101 memcpy (p, str, slen);
9104 simple_type = mono_class_enum_basetype (klass)->type;
9108 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9111 *retbuffer = buffer;
9115 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9117 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9118 char *str = type_get_qualified_name (type, NULL);
9119 int slen = strlen (str);
9123 * This seems to be optional...
9126 mono_metadata_encode_value (slen, p, &p);
9127 memcpy (p, str, slen);
9130 } else if (type->type == MONO_TYPE_OBJECT) {
9132 } else if (type->type == MONO_TYPE_CLASS) {
9133 /* it should be a type: encode_cattr_value () has the check */
9136 mono_metadata_encode_value (type->type, p, &p);
9137 if (type->type == MONO_TYPE_SZARRAY)
9138 /* See the examples in Partition VI, Annex B */
9139 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9145 #ifndef DISABLE_REFLECTION_EMIT
9147 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9150 /* Preallocate a large enough buffer */
9151 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9152 char *str = type_get_qualified_name (type, NULL);
9155 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9156 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9162 len += strlen (name);
9164 if ((p-buffer) + 20 + len >= *buflen) {
9168 newbuf = g_realloc (buffer, *buflen);
9169 p = newbuf + (p-buffer);
9173 encode_field_or_prop_type (type, p, &p);
9175 len = strlen (name);
9176 mono_metadata_encode_value (len, p, &p);
9177 memcpy (p, name, len);
9179 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9181 *retbuffer = buffer;
9185 * mono_reflection_get_custom_attrs_blob:
9186 * @ctor: custom attribute constructor
9187 * @ctorArgs: arguments o the constructor
9193 * Creates the blob of data that needs to be saved in the metadata and that represents
9194 * the custom attributed described by @ctor, @ctorArgs etc.
9195 * Returns: a Byte array representing the blob of data.
9198 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9201 MonoMethodSignature *sig;
9206 MONO_ARCH_SAVE_REGS;
9208 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9209 /* sig is freed later so allocate it in the heap */
9210 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9212 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9215 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9217 p = buffer = g_malloc (buflen);
9218 /* write the prolog */
9221 for (i = 0; i < sig->param_count; ++i) {
9222 arg = mono_array_get (ctorArgs, MonoObject*, i);
9223 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9227 i += mono_array_length (properties);
9229 i += mono_array_length (fields);
9231 *p++ = (i >> 8) & 0xff;
9234 for (i = 0; i < mono_array_length (properties); ++i) {
9238 prop = mono_array_get (properties, gpointer, i);
9239 get_prop_name_and_type (prop, &pname, &ptype);
9240 *p++ = 0x54; /* PROPERTY signature */
9241 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9248 for (i = 0; i < mono_array_length (fields); ++i) {
9252 field = mono_array_get (fields, gpointer, i);
9253 get_field_name_and_type (field, &fname, &ftype);
9254 *p++ = 0x53; /* FIELD signature */
9255 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9260 g_assert (p - buffer <= buflen);
9261 buflen = p - buffer;
9262 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9263 p = mono_array_addr (result, char, 0);
9264 memcpy (p, buffer, buflen);
9266 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9272 * mono_reflection_setup_internal_class:
9273 * @tb: a TypeBuilder object
9275 * Creates a MonoClass that represents the TypeBuilder.
9276 * This is a trick that lets us simplify a lot of reflection code
9277 * (and will allow us to support Build and Run assemblies easier).
9280 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9283 MonoClass *klass, *parent;
9285 MONO_ARCH_SAVE_REGS;
9287 RESOLVE_TYPE (tb->parent);
9289 mono_loader_lock ();
9292 /* check so we can compile corlib correctly */
9293 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9294 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9295 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9297 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9303 /* the type has already being created: it means we just have to change the parent */
9304 if (tb->type.type) {
9305 klass = mono_class_from_mono_type (tb->type.type);
9306 klass->parent = NULL;
9307 /* fool mono_class_setup_parent */
9308 klass->supertypes = NULL;
9309 mono_class_setup_parent (klass, parent);
9310 mono_class_setup_mono_type (klass);
9311 mono_loader_unlock ();
9315 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9317 klass->image = &tb->module->dynamic_image->image;
9319 klass->inited = 1; /* we lie to the runtime */
9320 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9321 if (!mono_error_ok (&error))
9323 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9324 if (!mono_error_ok (&error))
9326 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9327 klass->flags = tb->attrs;
9329 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9331 klass->element_class = klass;
9333 if (klass->reflection_info == NULL) {
9335 MOVING_GC_REGISTER (&klass->reflection_info);
9336 klass->reflection_info = tb;
9338 /* Put into cache so mono_class_get () will find it.
9339 Skip nested types as those should not be available on the global scope. */
9340 if (!tb->nesting_type) {
9341 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9343 klass->image->reflection_info_unregister_classes =
9344 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9347 g_assert (klass->reflection_info == tb);
9350 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9351 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9353 if (parent != NULL) {
9354 mono_class_setup_parent (klass, parent);
9355 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9356 const char *old_n = klass->name;
9357 /* trick to get relative numbering right when compiling corlib */
9358 klass->name = "BuildingObject";
9359 mono_class_setup_parent (klass, mono_defaults.object_class);
9360 klass->name = old_n;
9363 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9364 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9365 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9366 klass->instance_size = sizeof (MonoObject);
9367 klass->size_inited = 1;
9368 mono_class_setup_vtable_general (klass, NULL, 0);
9371 mono_class_setup_mono_type (klass);
9373 mono_class_setup_supertypes (klass);
9376 * FIXME: handle interfaces.
9379 tb->type.type = &klass->byval_arg;
9381 if (tb->nesting_type) {
9382 g_assert (tb->nesting_type->type);
9383 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9386 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9388 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9390 mono_loader_unlock ();
9394 mono_loader_unlock ();
9395 mono_error_raise_exception (&error);
9399 * mono_reflection_setup_generic_class:
9400 * @tb: a TypeBuilder object
9402 * Setup the generic class before adding the first generic parameter.
9405 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9410 * mono_reflection_create_generic_class:
9411 * @tb: a TypeBuilder object
9413 * Creates the generic class after all generic parameters have been added.
9416 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9421 MONO_ARCH_SAVE_REGS;
9423 klass = mono_class_from_mono_type (tb->type.type);
9425 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9427 if (klass->generic_container || (count == 0))
9430 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9432 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9434 klass->generic_container->owner.klass = klass;
9435 klass->generic_container->type_argc = count;
9436 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9438 klass->is_generic = 1;
9440 for (i = 0; i < count; i++) {
9441 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9442 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9443 klass->generic_container->type_params [i] = *param;
9444 /*Make sure we are a diferent type instance */
9445 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9446 klass->generic_container->type_params [i].info.pklass = NULL;
9448 g_assert (klass->generic_container->type_params [i].param.owner);
9451 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9455 * mono_reflection_create_internal_class:
9456 * @tb: a TypeBuilder object
9458 * Actually create the MonoClass that is associated with the TypeBuilder.
9461 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9465 MONO_ARCH_SAVE_REGS;
9467 klass = mono_class_from_mono_type (tb->type.type);
9469 mono_loader_lock ();
9470 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9471 MonoReflectionFieldBuilder *fb;
9473 MonoType *enum_basetype;
9475 g_assert (tb->fields != NULL);
9476 g_assert (mono_array_length (tb->fields) >= 1);
9478 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9480 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9481 mono_loader_unlock ();
9485 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9486 klass->element_class = mono_class_from_mono_type (enum_basetype);
9487 if (!klass->element_class)
9488 klass->element_class = mono_class_from_mono_type (enum_basetype);
9491 * get the element_class from the current corlib.
9493 ec = default_class_from_mono_type (enum_basetype);
9494 klass->instance_size = ec->instance_size;
9495 klass->size_inited = 1;
9497 * this is almost safe to do with enums and it's needed to be able
9498 * to create objects of the enum type (for use in SetConstant).
9500 /* FIXME: Does this mean enums can't have method overrides ? */
9501 mono_class_setup_vtable_general (klass, NULL, 0);
9503 mono_loader_unlock ();
9506 static MonoMarshalSpec*
9507 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9508 MonoReflectionMarshal *minfo)
9510 MonoMarshalSpec *res;
9512 res = image_g_new0 (image, MonoMarshalSpec, 1);
9513 res->native = minfo->type;
9515 switch (minfo->type) {
9516 case MONO_NATIVE_LPARRAY:
9517 res->data.array_data.elem_type = minfo->eltype;
9518 if (minfo->has_size) {
9519 res->data.array_data.param_num = minfo->param_num;
9520 res->data.array_data.num_elem = minfo->count;
9521 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9524 res->data.array_data.param_num = -1;
9525 res->data.array_data.num_elem = -1;
9526 res->data.array_data.elem_mult = -1;
9530 case MONO_NATIVE_BYVALTSTR:
9531 case MONO_NATIVE_BYVALARRAY:
9532 res->data.array_data.num_elem = minfo->count;
9535 case MONO_NATIVE_CUSTOM:
9536 if (minfo->marshaltyperef)
9537 res->data.custom_data.custom_name =
9538 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9540 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9549 #endif /* !DISABLE_REFLECTION_EMIT */
9551 MonoReflectionMarshal*
9552 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9553 MonoMarshalSpec *spec)
9555 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9556 MonoReflectionMarshal *minfo;
9559 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9560 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9561 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9562 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9565 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9566 minfo->type = spec->native;
9568 switch (minfo->type) {
9569 case MONO_NATIVE_LPARRAY:
9570 minfo->eltype = spec->data.array_data.elem_type;
9571 minfo->count = spec->data.array_data.num_elem;
9572 minfo->param_num = spec->data.array_data.param_num;
9575 case MONO_NATIVE_BYVALTSTR:
9576 case MONO_NATIVE_BYVALARRAY:
9577 minfo->count = spec->data.array_data.num_elem;
9580 case MONO_NATIVE_CUSTOM:
9581 if (spec->data.custom_data.custom_name) {
9582 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9584 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9586 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9588 if (spec->data.custom_data.cookie)
9589 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9599 #ifndef DISABLE_REFLECTION_EMIT
9601 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9602 ReflectionMethodBuilder *rmb,
9603 MonoMethodSignature *sig)
9607 MonoMethodNormal *pm;
9608 MonoMarshalSpec **specs;
9609 MonoReflectionMethodAux *method_aux;
9614 mono_error_init (&error);
9616 * Methods created using a MethodBuilder should have their memory allocated
9617 * inside the image mempool, while dynamic methods should have their memory
9620 dynamic = rmb->refs != NULL;
9621 image = dynamic ? NULL : klass->image;
9624 g_assert (!klass->generic_class);
9626 mono_loader_lock ();
9628 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9629 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9630 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9632 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9634 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9636 pm = (MonoMethodNormal*)m;
9638 m->dynamic = dynamic;
9640 m->flags = rmb->attrs;
9641 m->iflags = rmb->iattrs;
9642 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
9643 g_assert (mono_error_ok (&error));
9646 m->skip_visibility = rmb->skip_visibility;
9648 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9650 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9651 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9654 m->signature->pinvoke = 1;
9655 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9656 m->signature->pinvoke = 1;
9658 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9660 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
9661 g_assert (mono_error_ok (&error));
9662 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
9663 g_assert (mono_error_ok (&error));
9665 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9667 if (klass->image->dynamic)
9668 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9670 mono_loader_unlock ();
9673 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9674 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9675 MonoMethodHeader *header;
9677 gint32 max_stack, i;
9678 gint32 num_locals = 0;
9679 gint32 num_clauses = 0;
9683 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9684 code_size = rmb->ilgen->code_len;
9685 max_stack = rmb->ilgen->max_stack;
9686 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9687 if (rmb->ilgen->ex_handlers)
9688 num_clauses = method_count_clauses (rmb->ilgen);
9691 code = mono_array_addr (rmb->code, guint8, 0);
9692 code_size = mono_array_length (rmb->code);
9693 /* we probably need to run a verifier on the code... */
9703 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9704 header->code_size = code_size;
9705 header->code = image_g_malloc (image, code_size);
9706 memcpy ((char*)header->code, code, code_size);
9707 header->max_stack = max_stack;
9708 header->init_locals = rmb->init_locals;
9709 header->num_locals = num_locals;
9711 for (i = 0; i < num_locals; ++i) {
9712 MonoReflectionLocalBuilder *lb =
9713 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9715 header->locals [i] = image_g_new0 (image, MonoType, 1);
9716 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9719 header->num_clauses = num_clauses;
9721 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9722 rmb->ilgen, num_clauses);
9725 pm->header = header;
9728 if (rmb->generic_params) {
9729 int count = mono_array_length (rmb->generic_params);
9730 MonoGenericContainer *container;
9732 container = rmb->generic_container;
9734 m->is_generic = TRUE;
9735 mono_method_set_generic_container (m, container);
9737 container->type_argc = count;
9738 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9739 container->owner.method = m;
9741 for (i = 0; i < count; i++) {
9742 MonoReflectionGenericParam *gp =
9743 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9744 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9745 container->type_params [i] = *param;
9748 if (klass->generic_container) {
9749 container->parent = klass->generic_container;
9750 container->context.class_inst = klass->generic_container->context.class_inst;
9752 container->context.method_inst = mono_get_shared_generic_inst (container);
9756 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9760 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9762 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9763 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9764 for (i = 0; i < rmb->nrefs; ++i)
9765 data [i + 1] = rmb->refs [i];
9770 /* Parameter info */
9773 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9774 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9775 for (i = 0; i <= m->signature->param_count; ++i) {
9776 MonoReflectionParamBuilder *pb;
9777 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9778 if ((i > 0) && (pb->attrs)) {
9779 /* Make a copy since it might point to a shared type structure */
9780 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9781 m->signature->params [i - 1]->attrs = pb->attrs;
9784 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9785 MonoDynamicImage *assembly;
9786 guint32 idx, def_type, len;
9790 if (!method_aux->param_defaults) {
9791 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9792 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9794 assembly = (MonoDynamicImage*)klass->image;
9795 idx = encode_constant (assembly, pb->def_value, &def_type);
9796 /* Copy the data from the blob since it might get realloc-ed */
9797 p = assembly->blob.data + idx;
9798 len = mono_metadata_decode_blob_size (p, &p2);
9800 method_aux->param_defaults [i] = image_g_malloc (image, len);
9801 method_aux->param_default_types [i] = def_type;
9802 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9806 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
9807 g_assert (mono_error_ok (&error));
9810 if (!method_aux->param_cattr)
9811 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9812 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9818 /* Parameter marshalling */
9821 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9822 MonoReflectionParamBuilder *pb;
9823 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9824 if (pb->marshal_info) {
9826 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9827 specs [pb->position] =
9828 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9832 if (specs != NULL) {
9834 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9835 method_aux->param_marshall = specs;
9838 if (klass->image->dynamic && method_aux)
9839 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9841 mono_loader_unlock ();
9847 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9849 ReflectionMethodBuilder rmb;
9850 MonoMethodSignature *sig;
9852 mono_loader_lock ();
9853 sig = ctor_builder_to_signature (klass->image, mb);
9854 mono_loader_unlock ();
9856 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9858 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9859 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9861 /* If we are in a generic class, we might be called multiple times from inflate_method */
9862 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9863 /* ilgen is no longer needed */
9871 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9873 ReflectionMethodBuilder rmb;
9874 MonoMethodSignature *sig;
9876 mono_loader_lock ();
9877 sig = method_builder_to_signature (klass->image, mb);
9878 mono_loader_unlock ();
9880 reflection_methodbuilder_from_method_builder (&rmb, mb);
9882 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9883 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9885 /* If we are in a generic class, we might be called multiple times from inflate_method */
9886 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9887 /* ilgen is no longer needed */
9893 static MonoClassField*
9894 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9896 MonoClassField *field;
9899 field = g_new0 (MonoClassField, 1);
9901 field->name = mono_string_to_utf8 (fb->name);
9902 if (fb->attrs || fb->modreq || fb->modopt) {
9903 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
9904 field->type->attrs = fb->attrs;
9906 g_assert (klass->image->dynamic);
9907 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9908 g_free (field->type);
9909 field->type = custom;
9911 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9913 if (fb->offset != -1)
9914 field->offset = fb->offset;
9915 field->parent = klass;
9916 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9918 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9925 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9928 MonoReflectionTypeBuilder *tb = NULL;
9929 gboolean is_dynamic = FALSE;
9933 mono_loader_lock ();
9935 domain = mono_object_domain (type);
9937 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9938 tb = (MonoReflectionTypeBuilder *) type;
9941 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9942 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9944 tb = rgi->generic_type;
9948 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9949 if (tb && tb->generic_container)
9950 mono_reflection_create_generic_class (tb);
9952 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
9953 if (!klass->generic_container) {
9954 mono_loader_unlock ();
9958 if (klass->wastypebuilder) {
9959 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9964 mono_loader_unlock ();
9966 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9968 return &geninst->byval_arg;
9972 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9974 MonoGenericClass *gclass;
9975 MonoGenericInst *inst;
9977 g_assert (klass->generic_container);
9979 inst = mono_metadata_get_generic_inst (type_argc, types);
9980 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9982 return mono_generic_class_get_class (gclass);
9985 MonoReflectionMethod*
9986 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9989 MonoMethod *method, *inflated;
9990 MonoMethodInflated *imethod;
9991 MonoGenericContext tmp_context;
9992 MonoGenericInst *ginst;
9993 MonoType **type_argv;
9996 MONO_ARCH_SAVE_REGS;
9998 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9999 #ifndef DISABLE_REFLECTION_EMIT
10000 MonoReflectionMethodBuilder *mb = NULL;
10001 MonoReflectionTypeBuilder *tb;
10004 mb = (MonoReflectionMethodBuilder *) rmethod;
10005 tb = (MonoReflectionTypeBuilder *) mb->type;
10006 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10008 method = methodbuilder_to_mono_method (klass, mb);
10010 g_assert_not_reached ();
10014 method = rmethod->method;
10017 klass = method->klass;
10019 if (method->is_inflated)
10020 method = ((MonoMethodInflated *) method)->declaring;
10022 count = mono_method_signature (method)->generic_param_count;
10023 if (count != mono_array_length (types))
10026 type_argv = g_new0 (MonoType *, count);
10027 for (i = 0; i < count; i++) {
10028 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10029 type_argv [i] = mono_reflection_type_get_handle (garg);
10031 ginst = mono_metadata_get_generic_inst (count, type_argv);
10032 g_free (type_argv);
10034 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10035 tmp_context.method_inst = ginst;
10037 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10038 imethod = (MonoMethodInflated *) inflated;
10040 if (method->klass->image->dynamic) {
10041 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10043 * This table maps metadata structures representing inflated methods/fields
10044 * to the reflection objects representing their generic definitions.
10046 mono_loader_lock ();
10047 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10048 mono_loader_unlock ();
10051 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10054 #ifndef DISABLE_REFLECTION_EMIT
10056 static MonoMethod *
10057 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10059 MonoMethodInflated *imethod;
10060 MonoGenericContext *context;
10064 * With generic code sharing the klass might not be inflated.
10065 * This can happen because classes inflated with their own
10066 * type arguments are "normalized" to the uninflated class.
10068 if (!klass->generic_class)
10071 context = mono_class_get_context (klass);
10073 if (klass->method.count) {
10074 /* Find the already created inflated method */
10075 for (i = 0; i < klass->method.count; ++i) {
10076 g_assert (klass->methods [i]->is_inflated);
10077 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10080 g_assert (i < klass->method.count);
10081 imethod = (MonoMethodInflated*)klass->methods [i];
10083 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10086 if (method->is_generic && method->klass->image->dynamic) {
10087 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10089 mono_loader_lock ();
10090 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10091 mono_loader_unlock ();
10093 return (MonoMethod *) imethod;
10096 static MonoMethod *
10097 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
10099 MonoMethod *method;
10102 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type->generic_type));
10104 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10105 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10106 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10108 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10109 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10110 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10111 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10112 method = ((MonoReflectionMethod *) obj)->method;
10114 method = NULL; /* prevent compiler warning */
10115 g_error ("can't handle type %s", obj->vtable->klass->name);
10118 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10121 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10123 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10124 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10127 MonoGenericClass *gclass;
10128 MonoDynamicGenericClass *dgclass;
10129 MonoClass *klass, *gklass;
10133 MONO_ARCH_SAVE_REGS;
10135 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10136 klass = mono_class_from_mono_type (gtype);
10137 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10138 gclass = gtype->data.generic_class;
10140 g_assert (gclass->is_dynamic);
10141 dgclass = (MonoDynamicGenericClass *) gclass;
10143 if (dgclass->initialized)
10146 gklass = gclass->container_class;
10147 mono_class_init (gklass);
10149 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10150 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10151 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10152 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10153 dgclass->count_events = events ? mono_array_length (events) : 0;
10155 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10156 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10157 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10158 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10159 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10160 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10161 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10163 for (i = 0; i < dgclass->count_methods; i++) {
10164 MonoObject *obj = mono_array_get (methods, gpointer, i);
10166 dgclass->methods [i] = inflate_method (type, obj);
10169 for (i = 0; i < dgclass->count_ctors; i++) {
10170 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10172 dgclass->ctors [i] = inflate_method (type, obj);
10175 for (i = 0; i < dgclass->count_fields; i++) {
10176 MonoObject *obj = mono_array_get (fields, gpointer, i);
10177 MonoClassField *field, *inflated_field = NULL;
10179 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10180 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10181 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10182 field = ((MonoReflectionField *) obj)->field;
10184 field = NULL; /* prevent compiler warning */
10185 g_assert_not_reached ();
10188 dgclass->fields [i] = *field;
10189 dgclass->fields [i].parent = klass;
10190 dgclass->fields [i].type = mono_class_inflate_generic_type (
10191 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10192 dgclass->field_generic_types [i] = field->type;
10193 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10194 dgclass->field_objects [i] = obj;
10196 if (inflated_field) {
10197 g_free (inflated_field);
10199 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10203 for (i = 0; i < dgclass->count_properties; i++) {
10204 MonoObject *obj = mono_array_get (properties, gpointer, i);
10205 MonoProperty *property = &dgclass->properties [i];
10207 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10208 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10210 property->parent = klass;
10211 property->attrs = pb->attrs;
10212 property->name = mono_string_to_utf8 (pb->name);
10213 if (pb->get_method)
10214 property->get = inflate_method (type, (MonoObject *) pb->get_method);
10215 if (pb->set_method)
10216 property->set = inflate_method (type, (MonoObject *) pb->set_method);
10217 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10218 *property = *((MonoReflectionProperty *) obj)->property;
10219 property->name = g_strdup (property->name);
10222 property->get = inflate_mono_method (klass, property->get, NULL);
10224 property->set = inflate_mono_method (klass, property->set, NULL);
10226 g_assert_not_reached ();
10229 for (i = 0; i < dgclass->count_events; i++) {
10230 MonoObject *obj = mono_array_get (events, gpointer, i);
10231 MonoEvent *event = &dgclass->events [i];
10233 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10234 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10236 event->parent = klass;
10237 event->attrs = eb->attrs;
10238 event->name = mono_string_to_utf8 (eb->name);
10239 if (eb->add_method)
10240 event->add = inflate_method (type, (MonoObject *) eb->add_method);
10241 if (eb->remove_method)
10242 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
10243 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10244 *event = *((MonoReflectionMonoEvent *) obj)->event;
10245 event->name = g_strdup (event->name);
10248 event->add = inflate_mono_method (klass, event->add, NULL);
10250 event->remove = inflate_mono_method (klass, event->remove, NULL);
10252 g_assert_not_reached ();
10255 dgclass->initialized = TRUE;
10259 ensure_generic_class_runtime_vtable (MonoClass *klass)
10261 MonoClass *gklass = klass->generic_class->container_class;
10264 if (klass->wastypebuilder)
10267 ensure_runtime_vtable (gklass);
10269 klass->method.count = gklass->method.count;
10270 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10272 for (i = 0; i < klass->method.count; i++) {
10273 klass->methods [i] = mono_class_inflate_generic_method_full (
10274 gklass->methods [i], klass, mono_class_get_context (klass));
10277 klass->interface_count = gklass->interface_count;
10278 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10279 for (i = 0; i < klass->interface_count; ++i) {
10280 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10281 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10282 mono_metadata_free_type (iface_type);
10284 ensure_runtime_vtable (klass->interfaces [i]);
10286 klass->interfaces_inited = 1;
10288 /*We can only finish with this klass once it's parent has as well*/
10289 if (gklass->wastypebuilder)
10290 klass->wastypebuilder = TRUE;
10295 ensure_runtime_vtable (MonoClass *klass)
10297 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10300 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10303 ensure_runtime_vtable (klass->parent);
10306 num = tb->ctors? mono_array_length (tb->ctors): 0;
10307 num += tb->num_methods;
10308 klass->method.count = num;
10309 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10310 num = tb->ctors? mono_array_length (tb->ctors): 0;
10311 for (i = 0; i < num; ++i)
10312 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10313 num = tb->num_methods;
10315 for (i = 0; i < num; ++i)
10316 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10318 if (tb->interfaces) {
10319 klass->interface_count = mono_array_length (tb->interfaces);
10320 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10321 for (i = 0; i < klass->interface_count; ++i) {
10322 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10323 klass->interfaces [i] = mono_class_from_mono_type (iface);
10324 ensure_runtime_vtable (klass->interfaces [i]);
10326 klass->interfaces_inited = 1;
10328 } else if (klass->generic_class){
10329 ensure_generic_class_runtime_vtable (klass);
10332 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10333 for (i = 0; i < klass->method.count; ++i)
10334 klass->methods [i]->slot = i;
10336 mono_class_setup_interface_offsets (klass);
10337 mono_class_setup_interface_id (klass);
10341 * The generic vtable is needed even if image->run is not set since some
10342 * runtime code like ves_icall_Type_GetMethodsByName depends on
10343 * method->slot being defined.
10347 * tb->methods could not be freed since it is used for determining
10348 * overrides during dynamic vtable construction.
10353 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10355 MonoReflectionTypeBuilder *tb;
10359 *num_overrides = 0;
10361 g_assert (klass->image->dynamic);
10363 if (!klass->reflection_info)
10366 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10368 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10372 for (i = 0; i < tb->num_methods; ++i) {
10373 MonoReflectionMethodBuilder *mb =
10374 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10375 if (mb->override_method)
10381 *overrides = g_new0 (MonoMethod*, onum * 2);
10384 for (i = 0; i < tb->num_methods; ++i) {
10385 MonoReflectionMethodBuilder *mb =
10386 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10387 if (mb->override_method) {
10388 (*overrides) [onum * 2] =
10389 mb->override_method->method;
10390 (*overrides) [onum * 2 + 1] =
10393 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10394 g_assert (mb->override_method->method);
10395 g_assert (mb->mhandle);
10402 *num_overrides = onum;
10406 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10408 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10409 MonoReflectionFieldBuilder *fb;
10410 MonoClassField *field;
10411 MonoImage *image = klass->image;
10412 const char *p, *p2;
10414 guint32 len, idx, real_size = 0;
10416 klass->field.count = tb->num_fields;
10417 klass->field.first = 0;
10419 mono_error_init (error);
10421 if (tb->class_size) {
10422 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10423 klass->packing_size = tb->packing_size;
10424 real_size = klass->instance_size + tb->class_size;
10427 if (!klass->field.count) {
10428 klass->instance_size = MAX (klass->instance_size, real_size);
10432 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10433 mono_class_alloc_ext (klass);
10434 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10436 for (i = 0; i < klass->field.count; ++i) {
10437 fb = mono_array_get (tb->fields, gpointer, i);
10438 field = &klass->fields [i];
10439 field->name = mono_string_to_utf8_image (image, fb->name, error);
10440 if (!mono_error_ok (error))
10443 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10444 field->type->attrs = fb->attrs;
10446 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10448 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10449 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10450 if (fb->offset != -1)
10451 field->offset = fb->offset;
10452 field->parent = klass;
10453 fb->handle = field;
10454 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10456 if (fb->def_value) {
10457 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10458 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10459 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10460 /* Copy the data from the blob since it might get realloc-ed */
10461 p = assembly->blob.data + idx;
10462 len = mono_metadata_decode_blob_size (p, &p2);
10464 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10465 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10469 klass->instance_size = MAX (klass->instance_size, real_size);
10470 mono_class_layout_fields (klass);
10474 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10476 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10477 MonoReflectionPropertyBuilder *pb;
10478 MonoImage *image = klass->image;
10479 MonoProperty *properties;
10482 mono_error_init (error);
10485 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10487 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10488 klass->ext->property.first = 0;
10490 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10491 klass->ext->properties = properties;
10492 for (i = 0; i < klass->ext->property.count; ++i) {
10493 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10494 properties [i].parent = klass;
10495 properties [i].attrs = pb->attrs;
10496 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10497 if (!mono_error_ok (error))
10499 if (pb->get_method)
10500 properties [i].get = pb->get_method->mhandle;
10501 if (pb->set_method)
10502 properties [i].set = pb->set_method->mhandle;
10504 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10508 MonoReflectionEvent *
10509 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10511 MonoEvent *event = g_new0 (MonoEvent, 1);
10515 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10517 event->parent = klass;
10518 event->attrs = eb->attrs;
10519 event->name = mono_string_to_utf8 (eb->name);
10520 if (eb->add_method)
10521 event->add = eb->add_method->mhandle;
10522 if (eb->remove_method)
10523 event->remove = eb->remove_method->mhandle;
10524 if (eb->raise_method)
10525 event->raise = eb->raise_method->mhandle;
10527 if (eb->other_methods) {
10528 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10529 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10530 MonoReflectionMethodBuilder *mb =
10531 mono_array_get (eb->other_methods,
10532 MonoReflectionMethodBuilder*, j);
10533 event->other [j] = mb->mhandle;
10537 return mono_event_get_object (mono_object_domain (tb), klass, event);
10541 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10543 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10544 MonoReflectionEventBuilder *eb;
10545 MonoImage *image = klass->image;
10549 mono_error_init (error);
10552 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10554 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10555 klass->ext->event.first = 0;
10557 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10558 klass->ext->events = events;
10559 for (i = 0; i < klass->ext->event.count; ++i) {
10560 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10561 events [i].parent = klass;
10562 events [i].attrs = eb->attrs;
10563 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10564 if (!mono_error_ok (error))
10566 if (eb->add_method)
10567 events [i].add = eb->add_method->mhandle;
10568 if (eb->remove_method)
10569 events [i].remove = eb->remove_method->mhandle;
10570 if (eb->raise_method)
10571 events [i].raise = eb->raise_method->mhandle;
10573 if (eb->other_methods) {
10574 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10575 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10576 MonoReflectionMethodBuilder *mb =
10577 mono_array_get (eb->other_methods,
10578 MonoReflectionMethodBuilder*, j);
10579 events [i].other [j] = mb->mhandle;
10582 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10587 remove_instantiations_of (gpointer key,
10589 gpointer user_data)
10591 MonoType *type = (MonoType*)key;
10592 MonoClass *klass = (MonoClass*)user_data;
10594 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10601 check_array_for_usertypes (MonoArray *arr)
10608 for (i = 0; i < mono_array_length (arr); ++i)
10609 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10612 MonoReflectionType*
10613 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10617 MonoDomain* domain;
10618 MonoReflectionType* res;
10621 MONO_ARCH_SAVE_REGS;
10623 domain = mono_object_domain (tb);
10624 klass = mono_class_from_mono_type (tb->type.type);
10627 * Check for user defined Type subclasses.
10629 RESOLVE_TYPE (tb->parent);
10630 check_array_for_usertypes (tb->interfaces);
10632 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10633 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10635 RESOLVE_TYPE (fb->type);
10636 check_array_for_usertypes (fb->modreq);
10637 check_array_for_usertypes (fb->modopt);
10638 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10639 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10644 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10645 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10647 RESOLVE_TYPE (mb->rtype);
10648 check_array_for_usertypes (mb->return_modreq);
10649 check_array_for_usertypes (mb->return_modopt);
10650 check_array_for_usertypes (mb->parameters);
10651 if (mb->param_modreq)
10652 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10653 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10654 if (mb->param_modopt)
10655 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10656 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10661 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10662 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10664 check_array_for_usertypes (mb->parameters);
10665 if (mb->param_modreq)
10666 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10667 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10668 if (mb->param_modopt)
10669 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10670 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10675 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10678 * we need to lock the domain because the lock will be taken inside
10679 * So, we need to keep the locking order correct.
10681 mono_loader_lock ();
10682 mono_domain_lock (domain);
10683 if (klass->wastypebuilder) {
10684 mono_domain_unlock (domain);
10685 mono_loader_unlock ();
10686 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10689 * Fields to set in klass:
10690 * the various flags: delegate/unicode/contextbound etc.
10692 klass->flags = tb->attrs;
10693 klass->has_cctor = 1;
10694 klass->has_finalize = 1;
10697 if (!((MonoDynamicImage*)klass->image)->run) {
10698 if (klass->generic_container) {
10699 /* FIXME: The code below can't handle generic classes */
10700 klass->wastypebuilder = TRUE;
10701 mono_loader_unlock ();
10702 mono_domain_unlock (domain);
10703 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10708 /* enums are done right away */
10709 if (!klass->enumtype)
10710 ensure_runtime_vtable (klass);
10712 if (tb->subtypes) {
10713 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10714 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10715 mono_class_alloc_ext (klass);
10716 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)));
10720 klass->nested_classes_inited = TRUE;
10722 /* fields and object layout */
10723 if (klass->parent) {
10724 if (!klass->parent->size_inited)
10725 mono_class_init (klass->parent);
10726 klass->instance_size = klass->parent->instance_size;
10727 klass->sizes.class_size = 0;
10728 klass->min_align = klass->parent->min_align;
10729 /* if the type has no fields we won't call the field_setup
10730 * routine which sets up klass->has_references.
10732 klass->has_references |= klass->parent->has_references;
10734 klass->instance_size = sizeof (MonoObject);
10735 klass->min_align = 1;
10738 /* FIXME: handle packing_size and instance_size */
10739 typebuilder_setup_fields (klass, &error);
10740 if (!mono_error_ok (&error))
10742 typebuilder_setup_properties (klass, &error);
10743 if (!mono_error_ok (&error))
10746 typebuilder_setup_events (klass, &error);
10747 if (!mono_error_ok (&error))
10750 klass->wastypebuilder = TRUE;
10753 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10754 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10755 * we want to return normal System.MonoType objects, so clear these out from the cache.
10757 if (domain->type_hash && klass->generic_container)
10758 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10760 mono_domain_unlock (domain);
10761 mono_loader_unlock ();
10763 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10764 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10765 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10768 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10769 g_assert (res != (MonoReflectionType*)tb);
10774 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10775 klass->wastypebuilder = TRUE;
10776 mono_domain_unlock (domain);
10777 mono_loader_unlock ();
10778 mono_error_raise_exception (&error);
10783 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10785 MonoGenericParamFull *param;
10789 MONO_ARCH_SAVE_REGS;
10791 param = g_new0 (MonoGenericParamFull, 1);
10793 if (gparam->mbuilder) {
10794 if (!gparam->mbuilder->generic_container) {
10795 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10796 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10797 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10798 gparam->mbuilder->generic_container->is_method = TRUE;
10800 * Cannot set owner.method, since the MonoMethod is not created yet.
10801 * Set the image field instead, so type_in_image () works.
10803 gparam->mbuilder->generic_container->image = klass->image;
10805 param->param.owner = gparam->mbuilder->generic_container;
10806 } else if (gparam->tbuilder) {
10807 if (!gparam->tbuilder->generic_container) {
10808 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
10809 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10810 gparam->tbuilder->generic_container->owner.klass = klass;
10812 param->param.owner = gparam->tbuilder->generic_container;
10815 param->info.name = mono_string_to_utf8 (gparam->name);
10816 param->param.num = gparam->index;
10818 image = &gparam->tbuilder->module->dynamic_image->image;
10819 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10821 gparam->type.type = &pklass->byval_arg;
10823 MOVING_GC_REGISTER (&pklass->reflection_info);
10824 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10825 mono_image_lock (image);
10826 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
10827 mono_image_unlock (image);
10831 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10833 MonoReflectionModuleBuilder *module = sig->module;
10834 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
10835 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10840 check_array_for_usertypes (sig->arguments);
10842 sigbuffer_init (&buf, 32);
10844 sigbuffer_add_value (&buf, 0x07);
10845 sigbuffer_add_value (&buf, na);
10846 if (assembly != NULL){
10847 for (i = 0; i < na; ++i) {
10848 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10849 encode_reflection_type (assembly, type, &buf);
10853 buflen = buf.p - buf.buf;
10854 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10855 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10856 sigbuffer_free (&buf);
10862 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10864 MonoDynamicImage *assembly = sig->module->dynamic_image;
10865 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10870 check_array_for_usertypes (sig->arguments);
10872 sigbuffer_init (&buf, 32);
10874 sigbuffer_add_value (&buf, 0x06);
10875 for (i = 0; i < na; ++i) {
10876 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
10877 encode_reflection_type (assembly, type, &buf);
10880 buflen = buf.p - buf.buf;
10881 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10882 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10883 sigbuffer_free (&buf);
10889 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10891 ReflectionMethodBuilder rmb;
10892 MonoMethodSignature *sig;
10897 sig = dynamic_method_to_signature (mb);
10899 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10902 * Resolve references.
10905 * Every second entry in the refs array is reserved for storing handle_class,
10906 * which is needed by the ldtoken implementation in the JIT.
10908 rmb.nrefs = mb->nrefs;
10909 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10910 for (i = 0; i < mb->nrefs; i += 2) {
10911 MonoClass *handle_class;
10913 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10915 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10916 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10918 * The referenced DynamicMethod should already be created by the managed
10919 * code, except in the case of circular references. In that case, we store
10920 * method in the refs array, and fix it up later when the referenced
10921 * DynamicMethod is created.
10923 if (method->mhandle) {
10924 ref = method->mhandle;
10926 /* FIXME: GC object stored in unmanaged memory */
10929 /* FIXME: GC object stored in unmanaged memory */
10930 method->referenced_by = g_slist_append (method->referenced_by, mb);
10932 handle_class = mono_defaults.methodhandle_class;
10934 MonoException *ex = NULL;
10935 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10937 ex = mono_get_exception_type_load (NULL, NULL);
10938 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10939 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10943 mono_raise_exception (ex);
10948 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10949 rmb.refs [i + 1] = handle_class;
10952 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
10954 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10956 /* Fix up refs entries pointing at us */
10957 for (l = mb->referenced_by; l; l = l->next) {
10958 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10959 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10962 g_assert (method->mhandle);
10964 data = (gpointer*)wrapper->method_data;
10965 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10966 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10967 data [i + 1] = mb->mhandle;
10970 g_slist_free (mb->referenced_by);
10974 /* ilgen is no longer needed */
10978 #endif /* DISABLE_REFLECTION_EMIT */
10981 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10986 mono_runtime_free_method (
10987 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10992 * mono_reflection_is_valid_dynamic_token:
10994 * Returns TRUE if token is valid.
10998 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11000 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11003 #ifndef DISABLE_REFLECTION_EMIT
11006 * mono_reflection_lookup_dynamic_token:
11008 * Finish the Builder object pointed to by TOKEN and return the corresponding
11009 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11010 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11013 * LOCKING: Take the loader lock
11016 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11018 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11022 mono_loader_lock ();
11023 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11024 mono_loader_unlock ();
11027 g_error ("Could not find required dynamic token 0x%08x", token);
11033 handle_class = &klass;
11034 return resolve_object (image, obj, handle_class, context);
11038 * ensure_complete_type:
11040 * Ensure that KLASS is completed if it is a dynamic type, or references
11044 ensure_complete_type (MonoClass *klass)
11046 if (klass->image->dynamic && !klass->wastypebuilder) {
11047 MonoReflectionTypeBuilder *tb = klass->reflection_info;
11049 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11051 // Asserting here could break a lot of code
11052 //g_assert (klass->wastypebuilder);
11055 if (klass->generic_class) {
11056 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11059 for (i = 0; i < inst->type_argc; ++i) {
11060 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11066 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11068 gpointer result = NULL;
11070 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11071 result = mono_string_intern ((MonoString*)obj);
11072 *handle_class = mono_defaults.string_class;
11074 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11075 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11077 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11078 result = mono_class_from_mono_type (inflated);
11079 mono_metadata_free_type (inflated);
11081 result = mono_class_from_mono_type (type);
11083 *handle_class = mono_defaults.typehandle_class;
11085 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11086 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11087 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11088 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11089 result = ((MonoReflectionMethod*)obj)->method;
11091 result = mono_class_inflate_generic_method (result, context);
11092 *handle_class = mono_defaults.methodhandle_class;
11094 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11095 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11096 result = mb->mhandle;
11098 /* Type is not yet created */
11099 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11101 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11104 * Hopefully this has been filled in by calling CreateType() on the
11108 * TODO: This won't work if the application finishes another
11109 * TypeBuilder instance instead of this one.
11111 result = mb->mhandle;
11114 result = mono_class_inflate_generic_method (result, context);
11115 *handle_class = mono_defaults.methodhandle_class;
11116 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11117 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11119 result = cb->mhandle;
11121 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11123 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11124 result = cb->mhandle;
11127 result = mono_class_inflate_generic_method (result, context);
11128 *handle_class = mono_defaults.methodhandle_class;
11129 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11130 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11132 ensure_complete_type (field->parent);
11134 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11135 MonoClass *class = mono_class_from_mono_type (inflated);
11136 MonoClassField *inflated_field;
11137 gpointer iter = NULL;
11138 mono_metadata_free_type (inflated);
11139 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11140 if (!strcmp (field->name, inflated_field->name))
11143 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11144 result = inflated_field;
11148 *handle_class = mono_defaults.fieldhandle_class;
11150 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11151 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11152 result = fb->handle;
11155 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11157 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11158 result = fb->handle;
11161 if (fb->handle && fb->handle->parent->generic_container) {
11162 MonoClass *klass = fb->handle->parent;
11163 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11164 MonoClass *inflated = mono_class_from_mono_type (type);
11166 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11168 mono_metadata_free_type (type);
11170 *handle_class = mono_defaults.fieldhandle_class;
11171 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11172 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11173 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11176 klass = type->data.klass;
11177 if (klass->wastypebuilder) {
11178 /* Already created */
11182 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11183 result = type->data.klass;
11186 *handle_class = mono_defaults.typehandle_class;
11187 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11188 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11189 MonoMethodSignature *sig;
11192 if (helper->arguments)
11193 nargs = mono_array_length (helper->arguments);
11197 sig = mono_metadata_signature_alloc (image, nargs);
11198 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11199 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11201 if (helper->call_conv == 0) /* unmanaged */
11202 sig->call_convention = helper->unmanaged_call_conv - 1;
11204 if (helper->call_conv & 0x02)
11205 sig->call_convention = MONO_CALL_VARARG;
11207 sig->call_convention = MONO_CALL_DEFAULT;
11209 sig->param_count = nargs;
11210 /* TODO: Copy type ? */
11211 sig->ret = helper->return_type->type;
11212 for (i = 0; i < nargs; ++i)
11213 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11216 *handle_class = NULL;
11217 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11218 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11219 /* Already created by the managed code */
11220 g_assert (method->mhandle);
11221 result = method->mhandle;
11222 *handle_class = mono_defaults.methodhandle_class;
11223 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11224 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11225 type = mono_class_inflate_generic_type (type, context);
11226 result = mono_class_from_mono_type (type);
11227 *handle_class = mono_defaults.typehandle_class;
11229 mono_metadata_free_type (type);
11230 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11231 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11232 type = mono_class_inflate_generic_type (type, context);
11233 result = mono_class_from_mono_type (type);
11234 *handle_class = mono_defaults.typehandle_class;
11236 mono_metadata_free_type (type);
11237 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11238 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11239 MonoClass *inflated;
11242 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11243 inflated = mono_class_from_mono_type (type);
11245 g_assert (f->fb->handle);
11246 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
11248 mono_metadata_free_type (type);
11249 *handle_class = mono_defaults.fieldhandle_class;
11250 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11251 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11252 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11253 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11254 g_assert (c->cb->mhandle);
11255 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
11256 *handle_class = mono_defaults.methodhandle_class;
11257 mono_metadata_free_type (type);
11258 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11259 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11260 if (m->method_args) {
11261 result = mono_reflection_method_on_tb_inst_get_handle (m);
11263 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11264 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11265 g_assert (m->mb->mhandle);
11266 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
11267 mono_metadata_free_type (type);
11269 *handle_class = mono_defaults.methodhandle_class;
11270 } else if (is_sre_array (mono_object_get_class(obj)) ||
11271 is_sre_byref (mono_object_get_class(obj)) ||
11272 is_sre_pointer (mono_object_get_class(obj))) {
11273 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11274 MonoType *type = mono_reflection_type_get_handle (ref_type);
11275 result = mono_class_from_mono_type (type);
11276 *handle_class = mono_defaults.typehandle_class;
11278 g_print ("%s\n", obj->vtable->klass->name);
11279 g_assert_not_reached ();
11284 #else /* DISABLE_REFLECTION_EMIT */
11287 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11289 g_assert_not_reached ();
11294 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11296 g_assert_not_reached ();
11300 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11302 g_assert_not_reached ();
11306 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11308 g_assert_not_reached ();
11312 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11314 g_assert_not_reached ();
11318 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11320 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11324 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11326 g_assert_not_reached ();
11330 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11332 g_assert_not_reached ();
11335 MonoReflectionModule *
11336 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11338 g_assert_not_reached ();
11343 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11345 g_assert_not_reached ();
11350 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11352 g_assert_not_reached ();
11357 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11358 gboolean create_methodspec, gboolean register_token)
11360 g_assert_not_reached ();
11365 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11370 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11371 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11374 g_assert_not_reached ();
11378 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11381 *num_overrides = 0;
11384 MonoReflectionEvent *
11385 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11387 g_assert_not_reached ();
11391 MonoReflectionType*
11392 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11394 g_assert_not_reached ();
11399 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11401 g_assert_not_reached ();
11405 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11407 g_assert_not_reached ();
11412 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11414 g_assert_not_reached ();
11419 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11424 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11430 mono_reflection_type_get_handle (MonoReflectionType* ref)
11437 #endif /* DISABLE_REFLECTION_EMIT */
11439 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11440 const static guint32 declsec_flags_map[] = {
11441 0x00000000, /* empty */
11442 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11443 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11444 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11445 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11446 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11447 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11448 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11449 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11450 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11451 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11452 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11453 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11454 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11455 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11456 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11457 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11458 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11459 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11463 * Returns flags that includes all available security action associated to the handle.
11464 * @token: metadata token (either for a class or a method)
11465 * @image: image where resides the metadata.
11468 mono_declsec_get_flags (MonoImage *image, guint32 token)
11470 int index = mono_metadata_declsec_from_index (image, token);
11471 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11472 guint32 result = 0;
11476 /* HasSecurity can be present for other, not specially encoded, attributes,
11477 e.g. SuppressUnmanagedCodeSecurityAttribute */
11481 for (i = index; i < t->rows; i++) {
11482 guint32 cols [MONO_DECL_SECURITY_SIZE];
11484 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11485 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11488 action = cols [MONO_DECL_SECURITY_ACTION];
11489 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11490 result |= declsec_flags_map [action];
11492 g_assert_not_reached ();
11499 * Get the security actions (in the form of flags) associated with the specified method.
11501 * @method: The method for which we want the declarative security flags.
11502 * Return the declarative security flags for the method (only).
11504 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11505 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11508 mono_declsec_flags_from_method (MonoMethod *method)
11510 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11511 /* FIXME: No cache (for the moment) */
11512 guint32 idx = mono_method_get_index (method);
11513 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11514 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11515 return mono_declsec_get_flags (method->klass->image, idx);
11521 * Get the security actions (in the form of flags) associated with the specified class.
11523 * @klass: The class for which we want the declarative security flags.
11524 * Return the declarative security flags for the class.
11526 * Note: We cache the flags inside the MonoClass structure as this will get
11527 * called very often (at least for each method).
11530 mono_declsec_flags_from_class (MonoClass *klass)
11532 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11533 if (!klass->ext || !klass->ext->declsec_flags) {
11536 idx = mono_metadata_token_index (klass->type_token);
11537 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11538 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11539 mono_loader_lock ();
11540 mono_class_alloc_ext (klass);
11541 mono_loader_unlock ();
11542 /* we cache the flags on classes */
11543 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11545 return klass->ext->declsec_flags;
11551 * Get the security actions (in the form of flags) associated with the specified assembly.
11553 * @assembly: The assembly for which we want the declarative security flags.
11554 * Return the declarative security flags for the assembly.
11557 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11559 guint32 idx = 1; /* there is only one assembly */
11560 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11561 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11562 return mono_declsec_get_flags (assembly->image, idx);
11567 * Fill actions for the specific index (which may either be an encoded class token or
11568 * an encoded method token) from the metadata image.
11569 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11572 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11573 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11575 MonoBoolean result = FALSE;
11577 guint32 cols [MONO_DECL_SECURITY_SIZE];
11578 int index = mono_metadata_declsec_from_index (image, token);
11581 t = &image->tables [MONO_TABLE_DECLSECURITY];
11582 for (i = index; i < t->rows; i++) {
11583 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11585 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11588 /* if present only replace (class) permissions with method permissions */
11589 /* if empty accept either class or method permissions */
11590 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11591 if (!actions->demand.blob) {
11592 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11593 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11594 actions->demand.blob = (char*) (blob + 2);
11595 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11598 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11599 if (!actions->noncasdemand.blob) {
11600 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11601 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11602 actions->noncasdemand.blob = (char*) (blob + 2);
11603 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11606 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11607 if (!actions->demandchoice.blob) {
11608 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11609 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11610 actions->demandchoice.blob = (char*) (blob + 2);
11611 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11621 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11622 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11624 guint32 idx = mono_metadata_token_index (klass->type_token);
11625 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11626 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11627 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11631 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11632 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11634 guint32 idx = mono_method_get_index (method);
11635 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11636 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11637 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11641 * Collect all actions (that requires to generate code in mini) assigned for
11642 * the specified method.
11643 * Note: Don't use the content of actions if the function return FALSE.
11646 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11648 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11649 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11650 MonoBoolean result = FALSE;
11653 /* quick exit if no declarative security is present in the metadata */
11654 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11657 /* we want the original as the wrapper is "free" of the security informations */
11658 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11659 method = mono_marshal_method_from_wrapper (method);
11664 /* First we look for method-level attributes */
11665 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11666 mono_class_init (method->klass);
11667 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11669 result = mono_declsec_get_method_demands_params (method, demands,
11670 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11673 /* Here we use (or create) the class declarative cache to look for demands */
11674 flags = mono_declsec_flags_from_class (method->klass);
11675 if (flags & mask) {
11677 mono_class_init (method->klass);
11678 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11680 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11681 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11684 /* The boolean return value is used as a shortcut in case nothing needs to
11685 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11691 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11693 * Note: Don't use the content of actions if the function return FALSE.
11696 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11698 MonoBoolean result = FALSE;
11701 /* quick exit if no declarative security is present in the metadata */
11702 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11705 /* we want the original as the wrapper is "free" of the security informations */
11706 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11707 method = mono_marshal_method_from_wrapper (method);
11712 /* results are independant - zeroize both */
11713 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11714 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11716 /* First we look for method-level attributes */
11717 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11718 mono_class_init (method->klass);
11720 result = mono_declsec_get_method_demands_params (method, cmethod,
11721 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11724 /* Here we use (or create) the class declarative cache to look for demands */
11725 flags = mono_declsec_flags_from_class (method->klass);
11726 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11727 mono_class_init (method->klass);
11729 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11730 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11737 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11739 * @klass The inherited class - this is the class that provides the security check (attributes)
11741 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11743 * Note: Don't use the content of actions if the function return FALSE.
11746 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11748 MonoBoolean result = FALSE;
11751 /* quick exit if no declarative security is present in the metadata */
11752 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11755 /* Here we use (or create) the class declarative cache to look for demands */
11756 flags = mono_declsec_flags_from_class (klass);
11757 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11758 mono_class_init (klass);
11759 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11761 result |= mono_declsec_get_class_demands_params (klass, demands,
11762 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11769 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11771 * Note: Don't use the content of actions if the function return FALSE.
11774 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11776 /* quick exit if no declarative security is present in the metadata */
11777 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11780 /* we want the original as the wrapper is "free" of the security informations */
11781 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11782 method = mono_marshal_method_from_wrapper (method);
11787 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11788 mono_class_init (method->klass);
11789 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11791 return mono_declsec_get_method_demands_params (method, demands,
11792 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11799 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11801 guint32 cols [MONO_DECL_SECURITY_SIZE];
11805 int index = mono_metadata_declsec_from_index (image, token);
11809 t = &image->tables [MONO_TABLE_DECLSECURITY];
11810 for (i = index; i < t->rows; i++) {
11811 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11813 /* shortcut - index are ordered */
11814 if (token != cols [MONO_DECL_SECURITY_PARENT])
11817 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11818 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11819 entry->blob = (char*) (metadata + 2);
11820 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11829 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11831 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11832 guint32 idx = mono_method_get_index (method);
11833 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11834 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11835 return get_declsec_action (method->klass->image, idx, action, entry);
11841 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11844 guint32 flags = mono_declsec_flags_from_class (klass);
11845 if (declsec_flags_map [action] & flags) {
11846 guint32 idx = mono_metadata_token_index (klass->type_token);
11847 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11848 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11849 return get_declsec_action (klass->image, idx, action, entry);
11855 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11857 guint32 idx = 1; /* there is only one assembly */
11858 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11859 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11861 return get_declsec_action (assembly->image, idx, action, entry);
11865 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11867 MonoObject *res, *exc;
11869 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11870 static MonoMethod *method = NULL;
11872 if (!System_Reflection_Emit_TypeBuilder) {
11873 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11874 g_assert (System_Reflection_Emit_TypeBuilder);
11876 if (method == NULL) {
11877 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11882 * The result of mono_type_get_object () might be a System.MonoType but we
11883 * need a TypeBuilder so use klass->reflection_info.
11885 g_assert (klass->reflection_info);
11886 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11888 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11890 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11894 return *(MonoBoolean*)mono_object_unbox (res);