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)
58 static gboolean is_usertype (MonoReflectionType *ref);
59 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
67 #define TEXT_OFFSET 512
68 #define CLI_H_SIZE 136
69 #define FILE_ALIGN 512
70 #define VIRT_ALIGN 8192
71 #define START_TEXT_RVA 0x00002000
74 MonoReflectionILGen *ilgen;
75 MonoReflectionType *rtype;
76 MonoArray *parameters;
77 MonoArray *generic_params;
78 MonoGenericContainer *generic_container;
84 guint32 *table_idx; /* note: it's a pointer */
88 MonoBoolean init_locals;
89 MonoBoolean skip_visibility;
90 MonoArray *return_modreq;
91 MonoArray *return_modopt;
92 MonoArray *param_modreq;
93 MonoArray *param_modopt;
94 MonoArray *permissions;
99 int charset, extra_flags, native_cc;
100 MonoString *dll, *dllentry;
101 } ReflectionMethodBuilder;
105 MonoReflectionGenericParam *gparam;
106 } GenericParamTableEntry;
108 const unsigned char table_sizes [MONO_TABLE_NUM] = {
118 MONO_INTERFACEIMPL_SIZE,
119 MONO_MEMBERREF_SIZE, /* 0x0A */
121 MONO_CUSTOM_ATTR_SIZE,
122 MONO_FIELD_MARSHAL_SIZE,
123 MONO_DECL_SECURITY_SIZE,
124 MONO_CLASS_LAYOUT_SIZE,
125 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
126 MONO_STAND_ALONE_SIGNATURE_SIZE,
130 MONO_PROPERTY_MAP_SIZE,
133 MONO_METHOD_SEMA_SIZE,
134 MONO_METHODIMPL_SIZE,
135 MONO_MODULEREF_SIZE, /* 0x1A */
141 MONO_ASSEMBLY_SIZE, /* 0x20 */
142 MONO_ASSEMBLY_PROCESSOR_SIZE,
143 MONO_ASSEMBLYOS_SIZE,
144 MONO_ASSEMBLYREF_SIZE,
145 MONO_ASSEMBLYREFPROC_SIZE,
146 MONO_ASSEMBLYREFOS_SIZE,
150 MONO_NESTED_CLASS_SIZE,
152 MONO_GENERICPARAM_SIZE, /* 0x2A */
153 MONO_METHODSPEC_SIZE,
154 MONO_GENPARCONSTRAINT_SIZE
158 #ifndef DISABLE_REFLECTION_EMIT
159 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
160 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
161 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
162 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
163 static void ensure_runtime_vtable (MonoClass *klass);
164 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
165 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
166 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
167 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
173 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
174 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
175 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
176 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
177 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
178 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
179 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
180 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
181 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
182 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
183 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
184 static gboolean is_sre_array (MonoClass *class);
185 static gboolean is_sre_byref (MonoClass *class);
186 static gboolean is_sre_pointer (MonoClass *class);
187 static gboolean is_sre_type_builder (MonoClass *class);
188 static gboolean is_sre_method_builder (MonoClass *class);
189 static gboolean is_sre_ctor_builder (MonoClass *class);
190 static gboolean is_sre_field_builder (MonoClass *class);
191 static gboolean is_sr_mono_method (MonoClass *class);
192 static gboolean is_sr_mono_cmethod (MonoClass *class);
193 static gboolean is_sr_mono_field (MonoClass *class);
195 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
196 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
197 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
199 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type); \
203 mono_array_set (arr, MonoReflectionType*, index, __type); \
206 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
209 mono_reflection_init (void)
214 sigbuffer_init (SigBuffer *buf, int size)
216 buf->buf = g_malloc (size);
218 buf->end = buf->buf + size;
222 sigbuffer_make_room (SigBuffer *buf, int size)
224 if (buf->end - buf->p < size) {
225 int new_size = buf->end - buf->buf + size + 32;
226 char *p = g_realloc (buf->buf, new_size);
227 size = buf->p - buf->buf;
230 buf->end = buf->buf + new_size;
235 sigbuffer_add_value (SigBuffer *buf, guint32 val)
237 sigbuffer_make_room (buf, 6);
238 mono_metadata_encode_value (val, buf->p, &buf->p);
242 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
244 sigbuffer_make_room (buf, 1);
250 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
252 sigbuffer_make_room (buf, size);
253 memcpy (buf->p, p, size);
258 sigbuffer_free (SigBuffer *buf)
263 #ifndef DISABLE_REFLECTION_EMIT
267 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
271 image_g_malloc (MonoImage *image, guint size)
274 return mono_image_alloc (image, size);
276 return g_malloc (size);
278 #endif /* !DISABLE_REFLECTION_EMIT */
283 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
287 image_g_malloc0 (MonoImage *image, guint size)
290 return mono_image_alloc0 (image, size);
292 return g_malloc0 (size);
295 #ifndef DISABLE_REFLECTION_EMIT
297 image_strdup (MonoImage *image, const char *s)
300 return mono_image_strdup (image, s);
306 #define image_g_new(image,struct_type, n_structs) \
307 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
309 #define image_g_new0(image,struct_type, n_structs) \
310 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
314 alloc_table (MonoDynamicTable *table, guint nrows)
317 g_assert (table->columns);
318 if (nrows + 1 >= table->alloc_rows) {
319 while (nrows + 1 >= table->alloc_rows) {
320 if (table->alloc_rows == 0)
321 table->alloc_rows = 16;
323 table->alloc_rows *= 2;
326 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
331 make_room_in_stream (MonoDynamicStream *stream, int size)
333 if (size <= stream->alloc_size)
336 while (stream->alloc_size <= size) {
337 if (stream->alloc_size < 4096)
338 stream->alloc_size = 4096;
340 stream->alloc_size *= 2;
343 stream->data = g_realloc (stream->data, stream->alloc_size);
347 string_heap_insert (MonoDynamicStream *sh, const char *str)
351 gpointer oldkey, oldval;
353 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
354 return GPOINTER_TO_UINT (oldval);
356 len = strlen (str) + 1;
359 make_room_in_stream (sh, idx + len);
362 * We strdup the string even if we already copy them in sh->data
363 * so that the string pointers in the hash remain valid even if
364 * we need to realloc sh->data. We may want to avoid that later.
366 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
367 memcpy (sh->data + idx, str, len);
373 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
375 char *name = mono_string_to_utf8 (str);
377 idx = string_heap_insert (sh, name);
382 #ifndef DISABLE_REFLECTION_EMIT
384 string_heap_init (MonoDynamicStream *sh)
387 sh->alloc_size = 4096;
388 sh->data = g_malloc (4096);
389 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
390 string_heap_insert (sh, "");
395 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
399 make_room_in_stream (stream, stream->index + len);
400 memcpy (stream->data + stream->index, data, len);
402 stream->index += len;
404 * align index? Not without adding an additional param that controls it since
405 * we may store a blob value in pieces.
411 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
415 make_room_in_stream (stream, stream->index + len);
416 memset (stream->data + stream->index, 0, len);
418 stream->index += len;
423 stream_data_align (MonoDynamicStream *stream)
426 guint32 count = stream->index % 4;
428 /* we assume the stream data will be aligned */
430 mono_image_add_stream_data (stream, buf, 4 - count);
433 #ifndef DISABLE_REFLECTION_EMIT
435 mono_blob_entry_hash (const char* str)
439 len = mono_metadata_decode_blob_size (str, &str);
443 for (str += 1; str < end; str++)
444 h = (h << 5) - h + *str;
452 mono_blob_entry_equal (const char *str1, const char *str2) {
456 len = mono_metadata_decode_blob_size (str1, &end1);
457 len2 = mono_metadata_decode_blob_size (str2, &end2);
460 return memcmp (end1, end2, len) == 0;
464 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
468 gpointer oldkey, oldval;
470 copy = g_malloc (s1+s2);
471 memcpy (copy, b1, s1);
472 memcpy (copy + s1, b2, s2);
473 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
475 idx = GPOINTER_TO_UINT (oldval);
477 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
478 mono_image_add_stream_data (&assembly->blob, b2, s2);
479 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
485 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
489 guint32 size = buf->p - buf->buf;
491 g_assert (size <= (buf->end - buf->buf));
492 mono_metadata_encode_value (size, b, &b);
493 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
497 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
498 * dest may be misaligned.
501 swap_with_size (char *dest, const char* val, int len, int nelem) {
502 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
505 for (elem = 0; elem < nelem; ++elem) {
531 g_assert_not_reached ();
537 memcpy (dest, val, len * nelem);
542 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
546 guint32 idx = 0, len;
548 len = str->length * 2;
549 mono_metadata_encode_value (len, b, &b);
550 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
552 char *swapped = g_malloc (2 * mono_string_length (str));
553 const char *p = (const char*)mono_string_chars (str);
555 swap_with_size (swapped, p, 2, mono_string_length (str));
556 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
560 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
565 #ifndef DISABLE_REFLECTION_EMIT
567 default_class_from_mono_type (MonoType *type)
569 switch (type->type) {
570 case MONO_TYPE_OBJECT:
571 return mono_defaults.object_class;
573 return mono_defaults.void_class;
574 case MONO_TYPE_BOOLEAN:
575 return mono_defaults.boolean_class;
577 return mono_defaults.char_class;
579 return mono_defaults.sbyte_class;
581 return mono_defaults.byte_class;
583 return mono_defaults.int16_class;
585 return mono_defaults.uint16_class;
587 return mono_defaults.int32_class;
589 return mono_defaults.uint32_class;
591 return mono_defaults.int_class;
593 return mono_defaults.uint_class;
595 return mono_defaults.int64_class;
597 return mono_defaults.uint64_class;
599 return mono_defaults.single_class;
601 return mono_defaults.double_class;
602 case MONO_TYPE_STRING:
603 return mono_defaults.string_class;
605 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
606 g_assert_not_reached ();
614 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
617 MonoGenericInst *class_inst;
622 class_inst = gclass->context.class_inst;
624 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
625 klass = gclass->container_class;
626 sigbuffer_add_value (buf, klass->byval_arg.type);
627 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
629 sigbuffer_add_value (buf, class_inst->type_argc);
630 for (i = 0; i < class_inst->type_argc; ++i)
631 encode_type (assembly, class_inst->type_argv [i], buf);
636 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
639 g_assert_not_reached ();
644 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
648 case MONO_TYPE_BOOLEAN:
662 case MONO_TYPE_STRING:
663 case MONO_TYPE_OBJECT:
664 case MONO_TYPE_TYPEDBYREF:
665 sigbuffer_add_value (buf, type->type);
668 sigbuffer_add_value (buf, type->type);
669 encode_type (assembly, type->data.type, buf);
671 case MONO_TYPE_SZARRAY:
672 sigbuffer_add_value (buf, type->type);
673 encode_type (assembly, &type->data.klass->byval_arg, buf);
675 case MONO_TYPE_VALUETYPE:
676 case MONO_TYPE_CLASS: {
677 MonoClass *k = mono_class_from_mono_type (type);
679 if (k->generic_container) {
680 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
681 encode_generic_class (assembly, gclass, buf);
684 * Make sure we use the correct type.
686 sigbuffer_add_value (buf, k->byval_arg.type);
688 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
689 * otherwise two typerefs could point to the same type, leading to
690 * verification errors.
692 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
696 case MONO_TYPE_ARRAY:
697 sigbuffer_add_value (buf, type->type);
698 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
699 sigbuffer_add_value (buf, type->data.array->rank);
700 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
701 sigbuffer_add_value (buf, 0);
703 case MONO_TYPE_GENERICINST:
704 encode_generic_class (assembly, type->data.generic_class, buf);
708 sigbuffer_add_value (buf, type->type);
709 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
712 g_error ("need to encode type %x", type->type);
717 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
720 sigbuffer_add_value (buf, MONO_TYPE_VOID);
724 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
728 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
733 for (i = 0; i < mono_array_length (modreq); ++i) {
734 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
735 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
736 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
740 for (i = 0; i < mono_array_length (modopt); ++i) {
741 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
742 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
743 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
748 #ifndef DISABLE_REFLECTION_EMIT
750 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
754 guint32 nparams = sig->param_count;
760 sigbuffer_init (&buf, 32);
762 * FIXME: vararg, explicit_this, differenc call_conv values...
764 idx = sig->call_convention;
766 idx |= 0x20; /* hasthis */
767 if (sig->generic_param_count)
768 idx |= 0x10; /* generic */
769 sigbuffer_add_byte (&buf, idx);
770 if (sig->generic_param_count)
771 sigbuffer_add_value (&buf, sig->generic_param_count);
772 sigbuffer_add_value (&buf, nparams);
773 encode_type (assembly, sig->ret, &buf);
774 for (i = 0; i < nparams; ++i) {
775 if (i == sig->sentinelpos)
776 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
777 encode_type (assembly, sig->params [i], &buf);
779 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
780 sigbuffer_free (&buf);
786 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
789 * FIXME: reuse code from method_encode_signature().
793 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
794 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
795 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
798 sigbuffer_init (&buf, 32);
799 /* LAMESPEC: all the call conv spec is foobared */
800 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
801 if (mb->call_conv & 2)
802 idx |= 0x5; /* vararg */
803 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
804 idx |= 0x20; /* hasthis */
806 idx |= 0x10; /* generic */
807 sigbuffer_add_byte (&buf, idx);
809 sigbuffer_add_value (&buf, ngparams);
810 sigbuffer_add_value (&buf, nparams + notypes);
811 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
812 encode_reflection_type (assembly, mb->rtype, &buf);
813 for (i = 0; i < nparams; ++i) {
814 MonoArray *modreq = NULL;
815 MonoArray *modopt = NULL;
816 MonoReflectionType *pt;
818 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
819 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
820 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
821 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
822 encode_custom_modifiers (assembly, modreq, modopt, &buf);
823 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
824 encode_reflection_type (assembly, pt, &buf);
827 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
828 for (i = 0; i < notypes; ++i) {
829 MonoReflectionType *pt;
831 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
832 encode_reflection_type (assembly, pt, &buf);
835 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
836 sigbuffer_free (&buf);
841 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
843 MonoDynamicTable *table;
845 guint32 idx, sig_idx;
846 guint nl = mono_array_length (ilgen->locals);
850 sigbuffer_init (&buf, 32);
851 sigbuffer_add_value (&buf, 0x07);
852 sigbuffer_add_value (&buf, nl);
853 for (i = 0; i < nl; ++i) {
854 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
857 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
859 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
861 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
862 sigbuffer_free (&buf);
864 if (assembly->standalonesig_cache == NULL)
865 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
866 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
870 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
871 idx = table->next_idx ++;
873 alloc_table (table, table->rows);
874 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
876 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
878 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
884 method_count_clauses (MonoReflectionILGen *ilgen)
886 guint32 num_clauses = 0;
889 MonoILExceptionInfo *ex_info;
890 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
891 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
892 if (ex_info->handlers)
893 num_clauses += mono_array_length (ex_info->handlers);
901 #ifndef DISABLE_REFLECTION_EMIT
902 static MonoExceptionClause*
903 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
905 MonoExceptionClause *clauses;
906 MonoExceptionClause *clause;
907 MonoILExceptionInfo *ex_info;
908 MonoILExceptionBlock *ex_block;
909 guint32 finally_start;
910 int i, j, clause_index;;
912 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
915 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
916 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
917 finally_start = ex_info->start + ex_info->len;
918 if (!ex_info->handlers)
920 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
921 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
922 clause = &(clauses [clause_index]);
924 clause->flags = ex_block->type;
925 clause->try_offset = ex_info->start;
927 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
928 clause->try_len = finally_start - ex_info->start;
930 clause->try_len = ex_info->len;
931 clause->handler_offset = ex_block->start;
932 clause->handler_len = ex_block->len;
933 if (ex_block->extype) {
934 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
936 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
937 clause->data.filter_offset = ex_block->filter_offset;
939 clause->data.filter_offset = 0;
941 finally_start = ex_block->start + ex_block->len;
949 #endif /* !DISABLE_REFLECTION_EMIT */
952 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
958 gint32 num_locals = 0;
959 gint32 num_exception = 0;
962 char fat_header [12];
965 guint32 local_sig = 0;
966 guint32 header_size = 12;
969 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
970 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
974 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
976 code = mb->ilgen->code;
977 code_size = mb->ilgen->code_len;
978 max_stack = mb->ilgen->max_stack;
979 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
980 if (mb->ilgen->ex_handlers)
981 num_exception = method_count_clauses (mb->ilgen);
985 char *name = mono_string_to_utf8 (mb->name);
986 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
987 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
990 mono_raise_exception (exception);
993 code_size = mono_array_length (code);
994 max_stack = 8; /* we probably need to run a verifier on the code... */
997 stream_data_align (&assembly->code);
999 /* check for exceptions, maxstack, locals */
1000 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1002 if (code_size < 64 && !(code_size & 1)) {
1003 flags = (code_size << 2) | 0x2;
1004 } else if (code_size < 32 && (code_size & 1)) {
1005 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1009 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1010 /* add to the fixup todo list */
1011 if (mb->ilgen && mb->ilgen->num_token_fixups)
1012 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1013 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1014 return assembly->text_rva + idx;
1018 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1020 * FIXME: need to set also the header size in fat_flags.
1021 * (and more sects and init locals flags)
1025 fat_flags |= METHOD_HEADER_MORE_SECTS;
1026 if (mb->init_locals)
1027 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1028 fat_header [0] = fat_flags;
1029 fat_header [1] = (header_size / 4 ) << 4;
1030 short_value = GUINT16_TO_LE (max_stack);
1031 memcpy (fat_header + 2, &short_value, 2);
1032 int_value = GUINT32_TO_LE (code_size);
1033 memcpy (fat_header + 4, &int_value, 4);
1034 int_value = GUINT32_TO_LE (local_sig);
1035 memcpy (fat_header + 8, &int_value, 4);
1036 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1037 /* add to the fixup todo list */
1038 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1041 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1042 if (num_exception) {
1043 unsigned char sheader [4];
1044 MonoILExceptionInfo * ex_info;
1045 MonoILExceptionBlock * ex_block;
1048 stream_data_align (&assembly->code);
1049 /* always use fat format for now */
1050 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1051 num_exception *= 6 * sizeof (guint32);
1052 num_exception += 4; /* include the size of the header */
1053 sheader [1] = num_exception & 0xff;
1054 sheader [2] = (num_exception >> 8) & 0xff;
1055 sheader [3] = (num_exception >> 16) & 0xff;
1056 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1057 /* fat header, so we are already aligned */
1059 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1060 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1061 if (ex_info->handlers) {
1062 int finally_start = ex_info->start + ex_info->len;
1063 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1065 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1067 val = GUINT32_TO_LE (ex_block->type);
1068 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070 val = GUINT32_TO_LE (ex_info->start);
1071 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1072 /* need fault, too, probably */
1073 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1074 val = GUINT32_TO_LE (finally_start - ex_info->start);
1076 val = GUINT32_TO_LE (ex_info->len);
1077 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1078 /* handler offset */
1079 val = GUINT32_TO_LE (ex_block->start);
1080 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1082 val = GUINT32_TO_LE (ex_block->len);
1083 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1084 finally_start = ex_block->start + ex_block->len;
1085 if (ex_block->extype) {
1086 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1088 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1089 val = ex_block->filter_offset;
1093 val = GUINT32_TO_LE (val);
1094 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1095 /*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",
1096 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);*/
1099 g_error ("No clauses for ex info block %d", i);
1103 return assembly->text_rva + idx;
1107 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1110 MonoDynamicTable *table;
1113 table = &assembly->tables [table_idx];
1115 g_assert (col < table->columns);
1117 values = table->values + table->columns;
1118 for (i = 1; i <= table->rows; ++i) {
1119 if (values [col] == token)
1121 values += table->columns;
1127 * LOCKING: Acquires the loader lock.
1129 static MonoCustomAttrInfo*
1130 lookup_custom_attr (MonoImage *image, gpointer member)
1132 MonoCustomAttrInfo* res;
1134 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1139 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1143 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1145 /* FIXME: Need to do more checks */
1146 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1147 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1149 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1156 static MonoCustomAttrInfo*
1157 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1159 int i, index, count, not_visible;
1160 MonoCustomAttrInfo *ainfo;
1161 MonoReflectionCustomAttr *cattr;
1165 /* FIXME: check in assembly the Run flag is set */
1167 count = mono_array_length (cattrs);
1169 /* Skip nonpublic attributes since MS.NET seems to do the same */
1170 /* FIXME: This needs to be done more globally */
1172 for (i = 0; i < count; ++i) {
1173 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1174 if (!custom_attr_visible (image, cattr))
1177 count -= not_visible;
1179 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1181 ainfo->image = image;
1182 ainfo->num_attrs = count;
1183 ainfo->cached = alloc_img != NULL;
1185 for (i = 0; i < count; ++i) {
1186 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1187 if (custom_attr_visible (image, cattr)) {
1188 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1189 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1190 ainfo->attrs [index].ctor = cattr->ctor->method;
1191 ainfo->attrs [index].data = saved;
1192 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1200 #ifndef DISABLE_REFLECTION_EMIT
1202 * LOCKING: Acquires the loader lock.
1205 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1207 MonoCustomAttrInfo *ainfo, *tmp;
1209 if (!cattrs || !mono_array_length (cattrs))
1212 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1214 mono_loader_lock ();
1215 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1217 mono_custom_attrs_free (tmp);
1218 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1219 mono_loader_unlock ();
1225 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1232 * idx is the table index of the object
1233 * type is one of MONO_CUSTOM_ATTR_*
1236 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1238 MonoDynamicTable *table;
1239 MonoReflectionCustomAttr *cattr;
1241 guint32 count, i, token;
1243 char *p = blob_size;
1245 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1248 count = mono_array_length (cattrs);
1249 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1250 table->rows += count;
1251 alloc_table (table, table->rows);
1252 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1253 idx <<= MONO_CUSTOM_ATTR_BITS;
1255 for (i = 0; i < count; ++i) {
1256 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1257 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1258 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1259 type = mono_metadata_token_index (token);
1260 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1261 switch (mono_metadata_token_table (token)) {
1262 case MONO_TABLE_METHOD:
1263 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1265 case MONO_TABLE_MEMBERREF:
1266 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1269 g_warning ("got wrong token in custom attr");
1272 values [MONO_CUSTOM_ATTR_TYPE] = type;
1274 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1275 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1276 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1277 values += MONO_CUSTOM_ATTR_SIZE;
1283 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1285 MonoDynamicTable *table;
1287 guint32 count, i, idx;
1288 MonoReflectionPermissionSet *perm;
1293 count = mono_array_length (permissions);
1294 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1295 table->rows += count;
1296 alloc_table (table, table->rows);
1298 for (i = 0; i < mono_array_length (permissions); ++i) {
1299 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1301 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1303 idx = mono_metadata_token_index (parent_token);
1304 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1305 switch (mono_metadata_token_table (parent_token)) {
1306 case MONO_TABLE_TYPEDEF:
1307 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1309 case MONO_TABLE_METHOD:
1310 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1312 case MONO_TABLE_ASSEMBLY:
1313 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1316 g_assert_not_reached ();
1319 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1320 values [MONO_DECL_SECURITY_PARENT] = idx;
1321 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1328 * Fill in the MethodDef and ParamDef tables for a method.
1329 * This is used for both normal methods and constructors.
1332 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1334 MonoDynamicTable *table;
1338 /* room in this table is already allocated */
1339 table = &assembly->tables [MONO_TABLE_METHOD];
1340 *mb->table_idx = table->next_idx ++;
1341 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1342 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1343 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1344 values [MONO_METHOD_FLAGS] = mb->attrs;
1345 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1346 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1347 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1349 table = &assembly->tables [MONO_TABLE_PARAM];
1350 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1352 mono_image_add_decl_security (assembly,
1353 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1356 MonoDynamicTable *mtable;
1359 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1360 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1363 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1364 if (mono_array_get (mb->pinfo, gpointer, i))
1367 table->rows += count;
1368 alloc_table (table, table->rows);
1369 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1370 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1371 MonoReflectionParamBuilder *pb;
1372 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1373 values [MONO_PARAM_FLAGS] = pb->attrs;
1374 values [MONO_PARAM_SEQUENCE] = i;
1375 if (pb->name != NULL) {
1376 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1378 values [MONO_PARAM_NAME] = 0;
1380 values += MONO_PARAM_SIZE;
1381 if (pb->marshal_info) {
1383 alloc_table (mtable, mtable->rows);
1384 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1385 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1386 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1388 pb->table_idx = table->next_idx++;
1389 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1390 guint32 field_type = 0;
1391 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1393 alloc_table (mtable, mtable->rows);
1394 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1395 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1396 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1397 mvalues [MONO_CONSTANT_TYPE] = field_type;
1398 mvalues [MONO_CONSTANT_PADDING] = 0;
1406 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1408 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1410 rmb->ilgen = mb->ilgen;
1411 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1412 rmb->parameters = mb->parameters;
1413 rmb->generic_params = mb->generic_params;
1414 rmb->generic_container = mb->generic_container;
1415 rmb->opt_types = NULL;
1416 rmb->pinfo = mb->pinfo;
1417 rmb->attrs = mb->attrs;
1418 rmb->iattrs = mb->iattrs;
1419 rmb->call_conv = mb->call_conv;
1420 rmb->code = mb->code;
1421 rmb->type = mb->type;
1422 rmb->name = mb->name;
1423 rmb->table_idx = &mb->table_idx;
1424 rmb->init_locals = mb->init_locals;
1425 rmb->skip_visibility = FALSE;
1426 rmb->return_modreq = mb->return_modreq;
1427 rmb->return_modopt = mb->return_modopt;
1428 rmb->param_modreq = mb->param_modreq;
1429 rmb->param_modopt = mb->param_modopt;
1430 rmb->permissions = mb->permissions;
1431 rmb->mhandle = mb->mhandle;
1436 rmb->charset = mb->charset;
1437 rmb->extra_flags = mb->extra_flags;
1438 rmb->native_cc = mb->native_cc;
1439 rmb->dllentry = mb->dllentry;
1445 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1447 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1449 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1451 rmb->ilgen = mb->ilgen;
1452 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1453 rmb->parameters = mb->parameters;
1454 rmb->generic_params = NULL;
1455 rmb->generic_container = NULL;
1456 rmb->opt_types = NULL;
1457 rmb->pinfo = mb->pinfo;
1458 rmb->attrs = mb->attrs;
1459 rmb->iattrs = mb->iattrs;
1460 rmb->call_conv = mb->call_conv;
1462 rmb->type = mb->type;
1463 rmb->name = mono_string_new (mono_domain_get (), name);
1464 rmb->table_idx = &mb->table_idx;
1465 rmb->init_locals = mb->init_locals;
1466 rmb->skip_visibility = FALSE;
1467 rmb->return_modreq = NULL;
1468 rmb->return_modopt = NULL;
1469 rmb->param_modreq = mb->param_modreq;
1470 rmb->param_modopt = mb->param_modopt;
1471 rmb->permissions = mb->permissions;
1472 rmb->mhandle = mb->mhandle;
1477 #ifndef DISABLE_REFLECTION_EMIT
1479 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1481 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1483 rmb->ilgen = mb->ilgen;
1484 rmb->rtype = mb->rtype;
1485 rmb->parameters = mb->parameters;
1486 rmb->generic_params = NULL;
1487 rmb->generic_container = NULL;
1488 rmb->opt_types = NULL;
1490 rmb->attrs = mb->attrs;
1492 rmb->call_conv = mb->call_conv;
1494 rmb->type = (MonoObject *) mb->owner;
1495 rmb->name = mb->name;
1496 rmb->table_idx = NULL;
1497 rmb->init_locals = mb->init_locals;
1498 rmb->skip_visibility = mb->skip_visibility;
1499 rmb->return_modreq = NULL;
1500 rmb->return_modopt = NULL;
1501 rmb->param_modreq = NULL;
1502 rmb->param_modopt = NULL;
1503 rmb->permissions = NULL;
1504 rmb->mhandle = mb->mhandle;
1511 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1513 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1514 MonoDynamicTable *table;
1518 if (!mb->override_method)
1521 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1523 alloc_table (table, table->rows);
1524 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1525 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1526 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1528 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1529 switch (mono_metadata_token_table (tok)) {
1530 case MONO_TABLE_MEMBERREF:
1531 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1533 case MONO_TABLE_METHOD:
1534 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1537 g_assert_not_reached ();
1539 values [MONO_METHODIMPL_DECLARATION] = tok;
1543 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1545 MonoDynamicTable *table;
1547 ReflectionMethodBuilder rmb;
1550 reflection_methodbuilder_from_method_builder (&rmb, mb);
1552 mono_image_basic_method (&rmb, assembly);
1553 mb->table_idx = *rmb.table_idx;
1555 if (mb->dll) { /* It's a P/Invoke method */
1557 /* map CharSet values to on-disk values */
1558 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1559 int extra_flags = mb->extra_flags;
1560 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1562 alloc_table (table, table->rows);
1563 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1565 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1566 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1568 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1570 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1571 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1572 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1573 table = &assembly->tables [MONO_TABLE_MODULEREF];
1575 alloc_table (table, table->rows);
1576 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1577 values [MONO_IMPLMAP_SCOPE] = table->rows;
1581 if (mb->generic_params) {
1582 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1583 table->rows += mono_array_length (mb->generic_params);
1584 alloc_table (table, table->rows);
1585 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1586 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1588 mono_image_get_generic_param_info (
1589 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1596 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1598 ReflectionMethodBuilder rmb;
1600 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1602 mono_image_basic_method (&rmb, assembly);
1603 mb->table_idx = *rmb.table_idx;
1607 type_get_fully_qualified_name (MonoType *type)
1609 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1613 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1617 klass = mono_class_from_mono_type (type);
1619 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1620 ta = klass->image->assembly;
1621 if (ta->dynamic || (ta == ass)) {
1622 if (klass->generic_class || klass->generic_container)
1623 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1624 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1626 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1629 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1632 #ifndef DISABLE_REFLECTION_EMIT
1633 /*field_image is the image to which the eventual custom mods have been encoded against*/
1635 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1638 guint32 idx, i, token;
1640 if (!assembly->save)
1643 sigbuffer_init (&buf, 32);
1645 sigbuffer_add_value (&buf, 0x06);
1646 /* encode custom attributes before the type */
1647 if (type->num_mods) {
1648 for (i = 0; i < type->num_mods; ++i) {
1650 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1652 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1654 token = type->modifiers [i].token;
1657 if (type->modifiers [i].required)
1658 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1660 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1662 sigbuffer_add_value (&buf, token);
1665 encode_type (assembly, type, &buf);
1666 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1667 sigbuffer_free (&buf);
1673 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1678 sigbuffer_init (&buf, 32);
1680 sigbuffer_add_value (&buf, 0x06);
1681 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1682 /* encode custom attributes before the type */
1683 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1684 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1685 sigbuffer_free (&buf);
1690 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1691 char blob_size [64];
1692 char *b = blob_size;
1695 guint32 idx = 0, len = 0, dummy = 0;
1697 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1698 guint32 fpa_double [2];
1703 p = buf = g_malloc (64);
1705 *ret_type = MONO_TYPE_CLASS;
1707 box_val = (char*)&dummy;
1709 box_val = ((char*)val) + sizeof (MonoObject);
1710 *ret_type = val->vtable->klass->byval_arg.type;
1713 switch (*ret_type) {
1714 case MONO_TYPE_BOOLEAN:
1719 case MONO_TYPE_CHAR:
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737 fpa_p = (guint32*)box_val;
1738 fpa_double [0] = fpa_p [1];
1739 fpa_double [1] = fpa_p [0];
1740 box_val = (char*)fpa_double;
1744 case MONO_TYPE_VALUETYPE:
1745 if (val->vtable->klass->enumtype) {
1746 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1749 g_error ("we can't encode valuetypes");
1750 case MONO_TYPE_CLASS:
1752 case MONO_TYPE_STRING: {
1753 MonoString *str = (MonoString*)val;
1754 /* there is no signature */
1755 len = str->length * 2;
1756 mono_metadata_encode_value (len, b, &b);
1757 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1759 char *swapped = g_malloc (2 * mono_string_length (str));
1760 const char *p = (const char*)mono_string_chars (str);
1762 swap_with_size (swapped, p, 2, mono_string_length (str));
1763 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1767 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1773 case MONO_TYPE_GENERICINST:
1774 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1777 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1780 /* there is no signature */
1781 mono_metadata_encode_value (len, b, &b);
1782 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1783 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1784 swap_with_size (blob_size, box_val, len, 1);
1785 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1787 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1795 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1800 sigbuffer_init (&buf, 32);
1802 sigbuffer_add_value (&buf, minfo->type);
1804 switch (minfo->type) {
1805 case MONO_NATIVE_BYVALTSTR:
1806 case MONO_NATIVE_BYVALARRAY:
1807 sigbuffer_add_value (&buf, minfo->count);
1809 case MONO_NATIVE_LPARRAY:
1810 if (minfo->eltype || minfo->has_size) {
1811 sigbuffer_add_value (&buf, minfo->eltype);
1812 if (minfo->has_size) {
1813 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1814 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1816 /* LAMESPEC: ElemMult is undocumented */
1817 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1821 case MONO_NATIVE_SAFEARRAY:
1823 sigbuffer_add_value (&buf, minfo->eltype);
1825 case MONO_NATIVE_CUSTOM:
1827 str = mono_string_to_utf8 (minfo->guid);
1829 sigbuffer_add_value (&buf, len);
1830 sigbuffer_add_mem (&buf, str, len);
1833 sigbuffer_add_value (&buf, 0);
1835 /* native type name */
1836 sigbuffer_add_value (&buf, 0);
1837 /* custom marshaler type name */
1838 if (minfo->marshaltype || minfo->marshaltyperef) {
1839 if (minfo->marshaltyperef)
1840 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1842 str = mono_string_to_utf8 (minfo->marshaltype);
1844 sigbuffer_add_value (&buf, len);
1845 sigbuffer_add_mem (&buf, str, len);
1848 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1849 sigbuffer_add_value (&buf, 0);
1851 if (minfo->mcookie) {
1852 str = mono_string_to_utf8 (minfo->mcookie);
1854 sigbuffer_add_value (&buf, len);
1855 sigbuffer_add_mem (&buf, str, len);
1858 sigbuffer_add_value (&buf, 0);
1864 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1865 sigbuffer_free (&buf);
1870 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1872 MonoDynamicTable *table;
1875 /* maybe this fixup should be done in the C# code */
1876 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1877 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1878 table = &assembly->tables [MONO_TABLE_FIELD];
1879 fb->table_idx = table->next_idx ++;
1880 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1881 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1882 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1883 values [MONO_FIELD_FLAGS] = fb->attrs;
1884 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1886 if (fb->offset != -1) {
1887 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1889 alloc_table (table, table->rows);
1890 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1891 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1892 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1894 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1895 guint32 field_type = 0;
1896 table = &assembly->tables [MONO_TABLE_CONSTANT];
1898 alloc_table (table, table->rows);
1899 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1900 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1901 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1902 values [MONO_CONSTANT_TYPE] = field_type;
1903 values [MONO_CONSTANT_PADDING] = 0;
1905 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1907 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1909 alloc_table (table, table->rows);
1910 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1911 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1913 * We store it in the code section because it's simpler for now.
1916 if (mono_array_length (fb->rva_data) >= 10)
1917 stream_data_align (&assembly->code);
1918 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1920 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1921 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1923 if (fb->marshal_info) {
1924 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1926 alloc_table (table, table->rows);
1927 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1928 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1929 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1934 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1937 guint32 nparams = 0;
1938 MonoReflectionMethodBuilder *mb = fb->get_method;
1939 MonoReflectionMethodBuilder *smb = fb->set_method;
1942 if (mb && mb->parameters)
1943 nparams = mono_array_length (mb->parameters);
1944 if (!mb && smb && smb->parameters)
1945 nparams = mono_array_length (smb->parameters) - 1;
1946 sigbuffer_init (&buf, 32);
1947 sigbuffer_add_byte (&buf, 0x08);
1948 sigbuffer_add_value (&buf, nparams);
1950 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1951 for (i = 0; i < nparams; ++i) {
1952 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1953 encode_reflection_type (assembly, pt, &buf);
1955 } else if (smb && smb->parameters) {
1956 /* the property type is the last param */
1957 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1958 for (i = 0; i < nparams; ++i) {
1959 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1960 encode_reflection_type (assembly, pt, &buf);
1963 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1966 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1967 sigbuffer_free (&buf);
1972 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1974 MonoDynamicTable *table;
1976 guint num_methods = 0;
1980 * we need to set things in the following tables:
1981 * PROPERTYMAP (info already filled in _get_type_info ())
1982 * PROPERTY (rows already preallocated in _get_type_info ())
1983 * METHOD (method info already done with the generic method code)
1986 table = &assembly->tables [MONO_TABLE_PROPERTY];
1987 pb->table_idx = table->next_idx ++;
1988 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1989 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1990 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1991 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1993 /* FIXME: we still don't handle 'other' methods */
1994 if (pb->get_method) num_methods ++;
1995 if (pb->set_method) num_methods ++;
1997 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1998 table->rows += num_methods;
1999 alloc_table (table, table->rows);
2001 if (pb->get_method) {
2002 semaidx = table->next_idx ++;
2003 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2004 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2005 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2006 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2008 if (pb->set_method) {
2009 semaidx = table->next_idx ++;
2010 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2011 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2012 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2013 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2018 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2020 MonoDynamicTable *table;
2022 guint num_methods = 0;
2026 * we need to set things in the following tables:
2027 * EVENTMAP (info already filled in _get_type_info ())
2028 * EVENT (rows already preallocated in _get_type_info ())
2029 * METHOD (method info already done with the generic method code)
2032 table = &assembly->tables [MONO_TABLE_EVENT];
2033 eb->table_idx = table->next_idx ++;
2034 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2035 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2036 values [MONO_EVENT_FLAGS] = eb->attrs;
2037 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2040 * FIXME: we still don't handle 'other' methods
2042 if (eb->add_method) num_methods ++;
2043 if (eb->remove_method) num_methods ++;
2044 if (eb->raise_method) num_methods ++;
2046 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2047 table->rows += num_methods;
2048 alloc_table (table, table->rows);
2050 if (eb->add_method) {
2051 semaidx = table->next_idx ++;
2052 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2053 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2054 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2055 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2057 if (eb->remove_method) {
2058 semaidx = table->next_idx ++;
2059 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2061 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2062 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2064 if (eb->raise_method) {
2065 semaidx = table->next_idx ++;
2066 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2067 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2068 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2069 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2074 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2076 MonoDynamicTable *table;
2077 guint32 num_constraints, i;
2081 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2082 num_constraints = gparam->iface_constraints ?
2083 mono_array_length (gparam->iface_constraints) : 0;
2084 table->rows += num_constraints;
2085 if (gparam->base_type)
2087 alloc_table (table, table->rows);
2089 if (gparam->base_type) {
2090 table_idx = table->next_idx ++;
2091 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2093 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2094 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2095 assembly, mono_reflection_type_get_handle (gparam->base_type));
2098 for (i = 0; i < num_constraints; i++) {
2099 MonoReflectionType *constraint = mono_array_get (
2100 gparam->iface_constraints, gpointer, i);
2102 table_idx = table->next_idx ++;
2103 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2105 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2106 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2107 assembly, mono_reflection_type_get_handle (constraint));
2112 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2114 GenericParamTableEntry *entry;
2117 * The GenericParam table must be sorted according to the `owner' field.
2118 * We need to do this sorting prior to writing the GenericParamConstraint
2119 * table, since we have to use the final GenericParam table indices there
2120 * and they must also be sorted.
2123 entry = g_new0 (GenericParamTableEntry, 1);
2124 entry->owner = owner;
2125 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2126 MOVING_GC_REGISTER (&entry->gparam);
2127 entry->gparam = gparam;
2129 g_ptr_array_add (assembly->gen_params, entry);
2133 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2135 MonoDynamicTable *table;
2136 MonoGenericParam *param;
2140 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2141 table_idx = table->next_idx ++;
2142 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2144 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2146 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2147 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2148 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2149 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2151 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2153 encode_constraints (entry->gparam, table_idx, assembly);
2157 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2159 MonoDynamicTable *table;
2162 guint32 cols [MONO_ASSEMBLY_SIZE];
2166 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2169 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2170 table = &assembly->tables [MONO_TABLE_MODULEREF];
2171 token = table->next_idx ++;
2173 alloc_table (table, table->rows);
2174 values = table->values + token * MONO_MODULEREF_SIZE;
2175 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2177 token <<= MONO_RESOLTION_SCOPE_BITS;
2178 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2179 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2184 if (image->assembly->dynamic)
2186 memset (cols, 0, sizeof (cols));
2188 /* image->assembly->image is the manifest module */
2189 image = image->assembly->image;
2190 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2193 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2194 token = table->next_idx ++;
2196 alloc_table (table, table->rows);
2197 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2198 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2199 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2200 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2201 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2202 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2203 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2204 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2205 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2207 if (strcmp ("", image->assembly->aname.culture)) {
2208 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2209 image->assembly->aname.culture);
2212 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2213 guchar pubtoken [9];
2215 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2216 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2218 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2220 token <<= MONO_RESOLTION_SCOPE_BITS;
2221 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2222 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2227 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2229 MonoDynamicTable *table;
2234 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2237 sigbuffer_init (&buf, 32);
2238 switch (type->type) {
2239 case MONO_TYPE_FNPTR:
2241 case MONO_TYPE_SZARRAY:
2242 case MONO_TYPE_ARRAY:
2244 case MONO_TYPE_MVAR:
2245 case MONO_TYPE_GENERICINST:
2246 encode_type (assembly, type, &buf);
2248 case MONO_TYPE_CLASS:
2249 case MONO_TYPE_VALUETYPE: {
2250 MonoClass *k = mono_class_from_mono_type (type);
2251 if (!k || !k->generic_container) {
2252 sigbuffer_free (&buf);
2255 encode_type (assembly, type, &buf);
2259 sigbuffer_free (&buf);
2263 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2264 if (assembly->save) {
2265 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2266 alloc_table (table, table->rows + 1);
2267 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2268 values [MONO_TYPESPEC_SIGNATURE] = token;
2270 sigbuffer_free (&buf);
2272 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2273 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2279 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2281 MonoDynamicTable *table;
2283 guint32 token, scope, enclosing;
2286 /* if the type requires a typespec, we must try that first*/
2287 if (try_typespec && (token = create_typespec (assembly, type)))
2289 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2292 klass = mono_class_from_mono_type (type);
2294 klass = mono_class_from_mono_type (type);
2297 * If it's in the same module and not a generic type parameter:
2299 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2300 (type->type != MONO_TYPE_MVAR)) {
2301 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2302 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2303 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2307 if (klass->nested_in) {
2308 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2309 /* get the typeref idx of the enclosing type */
2310 enclosing >>= MONO_TYPEDEFORREF_BITS;
2311 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2313 scope = resolution_scope_from_image (assembly, klass->image);
2315 table = &assembly->tables [MONO_TABLE_TYPEREF];
2316 if (assembly->save) {
2317 alloc_table (table, table->rows + 1);
2318 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2319 values [MONO_TYPEREF_SCOPE] = scope;
2320 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2321 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2323 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2324 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2326 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2331 * Despite the name, we handle also TypeSpec (with the above helper).
2334 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2336 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2339 #ifndef DISABLE_REFLECTION_EMIT
2341 * Insert a memberef row into the metadata: the token that point to the memberref
2342 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2343 * mono_image_get_fieldref_token()).
2344 * The sig param is an index to an already built signature.
2347 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2349 MonoDynamicTable *table;
2351 guint32 token, pclass;
2354 parent = mono_image_typedef_or_ref (assembly, type);
2355 switch (parent & MONO_TYPEDEFORREF_MASK) {
2356 case MONO_TYPEDEFORREF_TYPEREF:
2357 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2359 case MONO_TYPEDEFORREF_TYPESPEC:
2360 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2362 case MONO_TYPEDEFORREF_TYPEDEF:
2363 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2366 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2369 /* extract the index */
2370 parent >>= MONO_TYPEDEFORREF_BITS;
2372 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2374 if (assembly->save) {
2375 alloc_table (table, table->rows + 1);
2376 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2377 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2378 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2379 values [MONO_MEMBERREF_SIGNATURE] = sig;
2382 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2389 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2392 MonoMethodSignature *sig;
2394 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2396 if (create_typespec) {
2397 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2402 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2403 if (token && !create_typespec)
2406 g_assert (!method->is_inflated);
2409 * A methodref signature can't contain an unmanaged calling convention.
2411 sig = mono_metadata_signature_dup (mono_method_signature (method));
2412 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2413 sig->call_convention = MONO_CALL_DEFAULT;
2414 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2415 method->name, method_encode_signature (assembly, sig));
2417 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2420 if (create_typespec) {
2421 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2422 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2423 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2425 if (assembly->save) {
2428 alloc_table (table, table->rows + 1);
2429 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2430 values [MONO_METHODSPEC_METHOD] = token;
2431 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2434 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2436 /*methodspec and memberef tokens are diferent, */
2437 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2444 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2447 ReflectionMethodBuilder rmb;
2450 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2454 name = mono_string_to_utf8 (method->name);
2455 reflection_methodbuilder_from_method_builder (&rmb, method);
2458 * A methodref signature can't contain an unmanaged calling convention.
2459 * Since some flags are encoded as part of call_conv, we need to check against it.
2461 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2462 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2463 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2464 name, method_builder_encode_signature (assembly, &rmb));
2467 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2472 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2473 const gchar *name, guint32 sig)
2475 MonoDynamicTable *table;
2479 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2481 if (assembly->save) {
2482 alloc_table (table, table->rows + 1);
2483 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2484 values [MONO_MEMBERREF_CLASS] = original;
2485 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2486 values [MONO_MEMBERREF_SIGNATURE] = sig;
2489 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2496 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2500 guint32 nparams = mono_array_length (mb->generic_params);
2503 if (!assembly->save)
2506 sigbuffer_init (&buf, 32);
2508 sigbuffer_add_value (&buf, 0xa);
2509 sigbuffer_add_value (&buf, nparams);
2511 for (i = 0; i < nparams; i++) {
2512 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2513 sigbuffer_add_value (&buf, i);
2516 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2517 sigbuffer_free (&buf);
2522 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2524 MonoDynamicTable *table;
2526 guint32 token, mtoken = 0;
2528 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2532 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2534 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2535 switch (mono_metadata_token_table (mtoken)) {
2536 case MONO_TABLE_MEMBERREF:
2537 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2539 case MONO_TABLE_METHOD:
2540 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2543 g_assert_not_reached ();
2546 if (assembly->save) {
2547 alloc_table (table, table->rows + 1);
2548 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2549 values [MONO_METHODSPEC_METHOD] = mtoken;
2550 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2553 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2556 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2561 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2565 if (mb->generic_params && create_methodspec)
2566 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2568 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2572 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2573 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2578 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2581 ReflectionMethodBuilder rmb;
2584 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2588 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2590 name = mono_string_to_utf8 (rmb.name);
2591 token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
2592 name, method_builder_encode_signature (assembly, &rmb));
2595 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2601 is_field_on_inst (MonoClassField *field)
2603 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2607 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2610 get_field_on_inst_generic_type (MonoClassField *field)
2612 MonoClass *class, *gtd;
2613 MonoDynamicGenericClass *dgclass;
2616 g_assert (is_field_on_inst (field));
2618 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2620 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2621 field_index = field - dgclass->fields;
2622 return dgclass->field_generic_types [field_index];
2625 class = field->parent;
2626 gtd = class->generic_class->container_class;
2628 if (field >= class->fields && field - class->fields < class->field.count) {
2629 field_index = field - class->fields;
2630 return gtd->fields [field_index].type;
2633 g_assert_not_reached ();
2637 #ifndef DISABLE_REFLECTION_EMIT
2639 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2643 MonoClassField *field;
2645 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2648 g_assert (f->field->parent);
2651 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2652 int index = field - field->parent->fields;
2653 type = field->parent->generic_class->container_class->fields [index].type;
2655 if (is_field_on_inst (f->field))
2656 type = get_field_on_inst_generic_type (f->field);
2658 type = f->field->type;
2660 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2661 mono_field_get_name (f->field),
2662 fieldref_encode_signature (assembly, field->parent->image, type));
2663 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2668 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2672 MonoGenericClass *gclass;
2673 MonoDynamicGenericClass *dgclass;
2677 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2680 if (is_sre_field_builder (mono_object_class (f->fb))) {
2681 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2682 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2683 klass = mono_class_from_mono_type (type);
2684 gclass = type->data.generic_class;
2685 g_assert (gclass->is_dynamic);
2686 dgclass = (MonoDynamicGenericClass *) gclass;
2688 name = mono_string_to_utf8 (fb->name);
2689 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2690 field_encode_signature (assembly, fb));
2692 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2694 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2696 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2697 klass = mono_class_from_mono_type (type);
2699 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2700 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2702 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2703 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2706 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2711 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2715 MonoGenericClass *gclass;
2718 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2720 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2724 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2725 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2726 MonoDynamicGenericClass *dgclass;
2727 ReflectionMethodBuilder rmb;
2730 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2731 klass = mono_class_from_mono_type (type);
2733 gclass = type->data.generic_class;
2734 g_assert (gclass->is_dynamic);
2735 dgclass = (MonoDynamicGenericClass *) gclass;
2737 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2739 name = mono_string_to_utf8 (rmb.name);
2741 sig = method_builder_encode_signature (assembly, &rmb);
2743 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2745 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2746 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2748 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2749 klass = mono_class_from_mono_type (type);
2751 sig = method_encode_signature (assembly, mono_method_signature (mm));
2752 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2754 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2755 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2759 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2764 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2767 MonoGenericContext tmp_context;
2768 MonoType **type_argv;
2769 MonoGenericInst *ginst;
2770 MonoMethod *method, *inflated;
2773 method = inflate_method (m->inst, (MonoObject*)m->mb);
2775 klass = method->klass;
2777 if (method->is_inflated)
2778 method = ((MonoMethodInflated *) method)->declaring;
2780 count = mono_array_length (m->method_args);
2782 type_argv = g_new0 (MonoType *, count);
2783 for (i = 0; i < count; i++) {
2784 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2785 type_argv [i] = mono_reflection_type_get_handle (garg);
2787 ginst = mono_metadata_get_generic_inst (count, type_argv);
2790 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2791 tmp_context.method_inst = ginst;
2793 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2798 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2800 guint32 sig, token = 0;
2804 if (m->method_args) {
2805 MonoMethod *inflated;
2807 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2808 if (create_methodspec)
2809 token = mono_image_get_methodspec_token (assembly, inflated);
2811 token = mono_image_get_inflated_method_token (assembly, inflated);
2815 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2819 if (is_sre_method_builder (mono_object_class (m->mb))) {
2820 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2821 MonoGenericClass *gclass;
2822 ReflectionMethodBuilder rmb;
2825 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2826 klass = mono_class_from_mono_type (type);
2827 gclass = type->data.generic_class;
2828 g_assert (gclass->is_dynamic);
2830 reflection_methodbuilder_from_method_builder (&rmb, mb);
2832 name = mono_string_to_utf8 (rmb.name);
2834 sig = method_builder_encode_signature (assembly, &rmb);
2836 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2838 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2839 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2841 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2842 klass = mono_class_from_mono_type (type);
2844 sig = method_encode_signature (assembly, mono_method_signature (mm));
2845 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2847 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2848 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2851 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2856 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2860 guint32 nparams = context->method_inst->type_argc;
2863 if (!assembly->save)
2866 sigbuffer_init (&buf, 32);
2868 * FIXME: vararg, explicit_this, differenc call_conv values...
2870 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2871 sigbuffer_add_value (&buf, nparams);
2873 for (i = 0; i < nparams; i++)
2874 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2876 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2877 sigbuffer_free (&buf);
2882 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2884 MonoDynamicTable *table;
2886 guint32 token, mtoken = 0, sig;
2887 MonoMethodInflated *imethod;
2888 MonoMethod *declaring;
2890 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2892 g_assert (method->is_inflated);
2893 imethod = (MonoMethodInflated *) method;
2894 declaring = imethod->declaring;
2896 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2897 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2899 if (!mono_method_signature (declaring)->generic_param_count)
2902 switch (mono_metadata_token_table (mtoken)) {
2903 case MONO_TABLE_MEMBERREF:
2904 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2906 case MONO_TABLE_METHOD:
2907 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2910 g_assert_not_reached ();
2913 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2915 if (assembly->save) {
2916 alloc_table (table, table->rows + 1);
2917 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2918 values [MONO_METHODSPEC_METHOD] = mtoken;
2919 values [MONO_METHODSPEC_SIGNATURE] = sig;
2922 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2929 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2931 MonoMethodInflated *imethod;
2934 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2938 g_assert (method->is_inflated);
2939 imethod = (MonoMethodInflated *) method;
2941 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2942 token = method_encode_methodspec (assembly, method);
2944 guint32 sig = method_encode_signature (
2945 assembly, mono_method_signature (imethod->declaring));
2946 token = mono_image_get_memberref_token (
2947 assembly, &method->klass->byval_arg, method->name, sig);
2950 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2955 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2957 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2960 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2961 token = mono_image_get_memberref_token (
2962 assembly, &m->klass->byval_arg, m->name, sig);
2968 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2970 MonoDynamicTable *table;
2979 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2980 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2981 * Because of this, we must not insert it into the `typeref' hash table.
2983 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
2984 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
2988 sigbuffer_init (&buf, 32);
2990 g_assert (tb->generic_params);
2991 klass = mono_class_from_mono_type (type);
2993 if (tb->generic_container)
2994 mono_reflection_create_generic_class (tb);
2996 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2997 g_assert (klass->generic_container);
2998 sigbuffer_add_value (&buf, klass->byval_arg.type);
2999 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3001 count = mono_array_length (tb->generic_params);
3002 sigbuffer_add_value (&buf, count);
3003 for (i = 0; i < count; i++) {
3004 MonoReflectionGenericParam *gparam;
3006 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3008 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3011 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3013 if (assembly->save) {
3014 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3015 alloc_table (table, table->rows + 1);
3016 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3017 values [MONO_TYPESPEC_SIGNATURE] = token;
3019 sigbuffer_free (&buf);
3021 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3022 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3028 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3031 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3033 int i, count, len, pos;
3038 count += mono_array_length (modreq);
3040 count += mono_array_length (modopt);
3043 return mono_metadata_type_dup (NULL, type);
3045 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3047 memcpy (t, type, MONO_SIZEOF_TYPE);
3049 t->num_mods = count;
3052 for (i = 0; i < mono_array_length (modreq); ++i) {
3053 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3054 t->modifiers [pos].required = 1;
3055 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3060 for (i = 0; i < mono_array_length (modopt); ++i) {
3061 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3062 t->modifiers [pos].required = 0;
3063 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3072 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3074 MonoDynamicTable *table;
3076 MonoType *custom = NULL;
3078 guint32 token, pclass, parent, sig;
3081 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
3085 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3086 name = mono_string_to_utf8 (fb->name);
3088 /* fb->type does not include the custom modifiers */
3089 /* FIXME: We should do this in one place when a fieldbuilder is created */
3090 if (fb->modreq || fb->modopt) {
3091 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3092 sig = fieldref_encode_signature (assembly, NULL, custom);
3095 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3098 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3099 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3101 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3102 parent >>= MONO_TYPEDEFORREF_BITS;
3104 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3106 if (assembly->save) {
3107 alloc_table (table, table->rows + 1);
3108 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3109 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3110 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3111 values [MONO_MEMBERREF_SIGNATURE] = sig;
3114 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3116 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
3122 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3129 if (!assembly->save)
3132 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3133 g_assert (helper->type == 2);
3135 if (helper->arguments)
3136 nargs = mono_array_length (helper->arguments);
3140 size = 10 + (nargs * 10);
3142 sigbuffer_init (&buf, 32);
3144 /* Encode calling convention */
3145 /* Change Any to Standard */
3146 if ((helper->call_conv & 0x03) == 0x03)
3147 helper->call_conv = 0x01;
3148 /* explicit_this implies has_this */
3149 if (helper->call_conv & 0x40)
3150 helper->call_conv &= 0x20;
3152 if (helper->call_conv == 0) { /* Unmanaged */
3153 idx = helper->unmanaged_call_conv - 1;
3156 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3157 if (helper->call_conv & 0x02) /* varargs */
3161 sigbuffer_add_byte (&buf, idx);
3162 sigbuffer_add_value (&buf, nargs);
3163 encode_reflection_type (assembly, helper->return_type, &buf);
3164 for (i = 0; i < nargs; ++i) {
3165 MonoArray *modreqs = NULL;
3166 MonoArray *modopts = NULL;
3167 MonoReflectionType *pt;
3169 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3170 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3171 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3172 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3174 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3175 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3176 encode_reflection_type (assembly, pt, &buf);
3178 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3179 sigbuffer_free (&buf);
3185 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3188 MonoDynamicTable *table;
3191 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3192 idx = table->next_idx ++;
3194 alloc_table (table, table->rows);
3195 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3197 values [MONO_STAND_ALONE_SIGNATURE] =
3198 mono_reflection_encode_sighelper (assembly, helper);
3204 reflection_cc_to_file (int call_conv) {
3205 switch (call_conv & 0x3) {
3207 case 1: return MONO_CALL_DEFAULT;
3208 case 2: return MONO_CALL_VARARG;
3210 g_assert_not_reached ();
3214 #endif /* !DISABLE_REFLECTION_EMIT */
3218 MonoMethodSignature *sig;
3223 #ifndef DISABLE_REFLECTION_EMIT
3225 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3230 MonoMethodSignature *sig;
3234 name = mono_string_to_utf8 (m->name);
3235 nparams = mono_array_length (m->parameters);
3236 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3238 sig->sentinelpos = -1;
3239 sig->call_convention = reflection_cc_to_file (m->call_conv);
3240 sig->param_count = nparams;
3241 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3242 mtype = mono_reflection_type_get_handle (m->parent);
3243 for (i = 0; i < nparams; ++i)
3244 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3246 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3248 if (strcmp (name, am->name) == 0 &&
3249 mono_metadata_type_equal (am->parent, mtype) &&
3250 mono_metadata_signature_equal (am->sig, sig)) {
3253 m->table_idx = am->token & 0xffffff;
3257 am = g_new0 (ArrayMethod, 1);
3261 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3262 method_encode_signature (assembly, sig));
3263 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3264 m->table_idx = am->token & 0xffffff;
3270 * Insert into the metadata tables all the info about the TypeBuilder tb.
3271 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3274 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3276 MonoDynamicTable *table;
3278 int i, is_object = 0, is_system = 0;
3281 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3282 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3283 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3284 n = mono_string_to_utf8 (tb->name);
3285 if (strcmp (n, "Object") == 0)
3287 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3289 n = mono_string_to_utf8 (tb->nspace);
3290 if (strcmp (n, "System") == 0)
3292 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3294 if (tb->parent && !(is_system && is_object) &&
3295 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3296 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3298 values [MONO_TYPEDEF_EXTENDS] = 0;
3300 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3301 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3304 * if we have explicitlayout or sequentiallayouts, output data in the
3305 * ClassLayout table.
3307 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3308 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3309 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3311 alloc_table (table, table->rows);
3312 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3313 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3314 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3315 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3318 /* handle interfaces */
3319 if (tb->interfaces) {
3320 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3322 table->rows += mono_array_length (tb->interfaces);
3323 alloc_table (table, table->rows);
3324 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3325 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3326 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3327 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3328 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3329 values += MONO_INTERFACEIMPL_SIZE;
3335 table = &assembly->tables [MONO_TABLE_FIELD];
3336 table->rows += tb->num_fields;
3337 alloc_table (table, table->rows);
3338 for (i = 0; i < tb->num_fields; ++i)
3339 mono_image_get_field_info (
3340 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3343 /* handle constructors */
3345 table = &assembly->tables [MONO_TABLE_METHOD];
3346 table->rows += mono_array_length (tb->ctors);
3347 alloc_table (table, table->rows);
3348 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3349 mono_image_get_ctor_info (domain,
3350 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3353 /* handle methods */
3355 table = &assembly->tables [MONO_TABLE_METHOD];
3356 table->rows += tb->num_methods;
3357 alloc_table (table, table->rows);
3358 for (i = 0; i < tb->num_methods; ++i)
3359 mono_image_get_method_info (
3360 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3363 /* Do the same with properties etc.. */
3364 if (tb->events && mono_array_length (tb->events)) {
3365 table = &assembly->tables [MONO_TABLE_EVENT];
3366 table->rows += mono_array_length (tb->events);
3367 alloc_table (table, table->rows);
3368 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3370 alloc_table (table, table->rows);
3371 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3372 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3373 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3374 for (i = 0; i < mono_array_length (tb->events); ++i)
3375 mono_image_get_event_info (
3376 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3378 if (tb->properties && mono_array_length (tb->properties)) {
3379 table = &assembly->tables [MONO_TABLE_PROPERTY];
3380 table->rows += mono_array_length (tb->properties);
3381 alloc_table (table, table->rows);
3382 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3384 alloc_table (table, table->rows);
3385 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3386 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3387 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3388 for (i = 0; i < mono_array_length (tb->properties); ++i)
3389 mono_image_get_property_info (
3390 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3393 /* handle generic parameters */
3394 if (tb->generic_params) {
3395 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3396 table->rows += mono_array_length (tb->generic_params);
3397 alloc_table (table, table->rows);
3398 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3399 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3401 mono_image_get_generic_param_info (
3402 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3406 mono_image_add_decl_security (assembly,
3407 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3410 MonoDynamicTable *ntable;
3412 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3413 ntable->rows += mono_array_length (tb->subtypes);
3414 alloc_table (ntable, ntable->rows);
3415 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3417 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3418 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3420 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3421 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3422 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3423 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3424 mono_string_to_utf8 (tb->name), tb->table_idx,
3425 ntable->next_idx, ntable->rows);*/
3426 values += MONO_NESTED_CLASS_SIZE;
3433 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3437 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3439 if (!type->subtypes)
3442 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3443 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3444 collect_types (types, subtype);
3449 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3451 if ((*type1)->table_idx < (*type2)->table_idx)
3454 if ((*type1)->table_idx > (*type2)->table_idx)
3461 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3466 for (i = 0; i < mono_array_length (pinfo); ++i) {
3467 MonoReflectionParamBuilder *pb;
3468 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3471 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3476 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3479 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3481 for (i = 0; i < tb->num_fields; ++i) {
3482 MonoReflectionFieldBuilder* fb;
3483 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3484 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3488 for (i = 0; i < mono_array_length (tb->events); ++i) {
3489 MonoReflectionEventBuilder* eb;
3490 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3491 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3494 if (tb->properties) {
3495 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3496 MonoReflectionPropertyBuilder* pb;
3497 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3498 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3502 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3503 MonoReflectionCtorBuilder* cb;
3504 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3505 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3506 params_add_cattrs (assembly, cb->pinfo);
3511 for (i = 0; i < tb->num_methods; ++i) {
3512 MonoReflectionMethodBuilder* mb;
3513 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3514 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3515 params_add_cattrs (assembly, mb->pinfo);
3520 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3521 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3526 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3530 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3532 if (moduleb->global_methods) {
3533 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3534 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3535 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3536 params_add_cattrs (assembly, mb->pinfo);
3540 if (moduleb->global_fields) {
3541 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3542 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3543 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3547 if (moduleb->types) {
3548 for (i = 0; i < moduleb->num_types; ++i)
3549 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3554 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3556 MonoDynamicTable *table;
3560 char *b = blob_size;
3563 table = &assembly->tables [MONO_TABLE_FILE];
3565 alloc_table (table, table->rows);
3566 values = table->values + table->next_idx * MONO_FILE_SIZE;
3567 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3568 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3569 if (module->image->dynamic) {
3570 /* This depends on the fact that the main module is emitted last */
3571 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3572 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3575 path = g_strdup (module->image->name);
3577 mono_sha1_get_digest_from_file (path, hash);
3580 mono_metadata_encode_value (20, b, &b);
3581 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3582 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3587 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3589 MonoDynamicTable *table;
3592 table = &assembly->tables [MONO_TABLE_MODULE];
3593 mb->table_idx = table->next_idx ++;
3594 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3595 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3598 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3599 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3600 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3601 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3605 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3606 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3608 MonoDynamicTable *table;
3612 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3613 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3616 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3618 alloc_table (table, table->rows);
3619 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3621 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3622 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3623 if (klass->nested_in)
3624 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3626 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3627 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3628 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3630 res = table->next_idx;
3634 /* Emit nested types */
3635 if (klass->ext && klass->ext->nested_classes) {
3638 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3639 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3646 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3647 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3652 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3654 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3656 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3657 parent_index, assembly);
3661 * We need to do this ourselves since klass->nested_classes is not set up.
3664 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3665 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3670 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3671 guint32 module_index, MonoDynamicImage *assembly)
3673 MonoImage *image = module->image;
3677 t = &image->tables [MONO_TABLE_TYPEDEF];
3679 for (i = 0; i < t->rows; ++i) {
3680 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3682 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3683 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3688 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3690 MonoDynamicTable *table;
3692 guint32 scope, idx, res, impl;
3693 gboolean forwarder = TRUE;
3695 if (klass->nested_in) {
3696 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3699 scope = resolution_scope_from_image (assembly, klass->image);
3700 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3701 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3702 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3705 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3708 alloc_table (table, table->rows);
3709 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3711 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3712 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3713 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3714 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3715 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3717 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3725 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3730 if (!assemblyb->type_forwarders)
3733 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3734 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3739 type = mono_reflection_type_get_handle (t);
3742 klass = mono_class_from_mono_type (type);
3744 add_exported_type (assemblyb, assembly, klass);
3748 #define align_pointer(base,p)\
3750 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3752 (p) += 4 - (__diff & 3);\
3756 compare_constants (const void *a, const void *b)
3758 const guint32 *a_values = a;
3759 const guint32 *b_values = b;
3760 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3764 compare_semantics (const void *a, const void *b)
3766 const guint32 *a_values = a;
3767 const guint32 *b_values = b;
3768 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3771 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3775 compare_custom_attrs (const void *a, const void *b)
3777 const guint32 *a_values = a;
3778 const guint32 *b_values = b;
3780 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3784 compare_field_marshal (const void *a, const void *b)
3786 const guint32 *a_values = a;
3787 const guint32 *b_values = b;
3789 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3793 compare_nested (const void *a, const void *b)
3795 const guint32 *a_values = a;
3796 const guint32 *b_values = b;
3798 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3802 compare_genericparam (const void *a, const void *b)
3804 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3805 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3807 if ((*b_entry)->owner == (*a_entry)->owner)
3809 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3810 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3812 return (*a_entry)->owner - (*b_entry)->owner;
3816 compare_declsecurity_attrs (const void *a, const void *b)
3818 const guint32 *a_values = a;
3819 const guint32 *b_values = b;
3821 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3825 compare_interface_impl (const void *a, const void *b)
3827 const guint32 *a_values = a;
3828 const guint32 *b_values = b;
3830 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3834 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3838 pad_heap (MonoDynamicStream *sh)
3840 if (sh->index & 3) {
3841 int sz = 4 - (sh->index & 3);
3842 memset (sh->data + sh->index, 0, sz);
3849 MonoDynamicStream *stream;
3853 * build_compressed_metadata() fills in the blob of data that represents the
3854 * raw metadata as it will be saved in the PE file. The five streams are output
3855 * and the metadata tables are comnpressed from the guint32 array representation,
3856 * to the compressed on-disk format.
3859 build_compressed_metadata (MonoDynamicImage *assembly)
3861 MonoDynamicTable *table;
3863 guint64 valid_mask = 0;
3864 guint64 sorted_mask;
3865 guint32 heapt_size = 0;
3866 guint32 meta_size = 256; /* allow for header and other stuff */
3867 guint32 table_offset;
3868 guint32 ntables = 0;
3874 struct StreamDesc stream_desc [5];
3876 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3877 for (i = 0; i < assembly->gen_params->len; i++){
3878 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3879 write_generic_param_entry (assembly, entry);
3882 stream_desc [0].name = "#~";
3883 stream_desc [0].stream = &assembly->tstream;
3884 stream_desc [1].name = "#Strings";
3885 stream_desc [1].stream = &assembly->sheap;
3886 stream_desc [2].name = "#US";
3887 stream_desc [2].stream = &assembly->us;
3888 stream_desc [3].name = "#Blob";
3889 stream_desc [3].stream = &assembly->blob;
3890 stream_desc [4].name = "#GUID";
3891 stream_desc [4].stream = &assembly->guid;
3893 /* tables that are sorted */
3894 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3895 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3896 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3897 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3898 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3899 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3900 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3902 /* Compute table sizes */
3903 /* the MonoImage has already been created in mono_image_basic_init() */
3904 meta = &assembly->image;
3906 /* sizes should be multiple of 4 */
3907 pad_heap (&assembly->blob);
3908 pad_heap (&assembly->guid);
3909 pad_heap (&assembly->sheap);
3910 pad_heap (&assembly->us);
3912 /* Setup the info used by compute_sizes () */
3913 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3914 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3915 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3917 meta_size += assembly->blob.index;
3918 meta_size += assembly->guid.index;
3919 meta_size += assembly->sheap.index;
3920 meta_size += assembly->us.index;
3922 for (i=0; i < MONO_TABLE_NUM; ++i)
3923 meta->tables [i].rows = assembly->tables [i].rows;
3925 for (i = 0; i < MONO_TABLE_NUM; i++){
3926 if (meta->tables [i].rows == 0)
3928 valid_mask |= (guint64)1 << i;
3930 meta->tables [i].row_size = mono_metadata_compute_size (
3931 meta, i, &meta->tables [i].size_bitfield);
3932 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3934 heapt_size += 24; /* #~ header size */
3935 heapt_size += ntables * 4;
3936 /* make multiple of 4 */
3939 meta_size += heapt_size;
3940 meta->raw_metadata = g_malloc0 (meta_size);
3941 p = (unsigned char*)meta->raw_metadata;
3942 /* the metadata signature */
3943 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3944 /* version numbers and 4 bytes reserved */
3945 int16val = (guint16*)p;
3946 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3947 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3949 /* version string */
3950 int32val = (guint32*)p;
3951 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3953 memcpy (p, meta->version, strlen (meta->version));
3954 p += GUINT32_FROM_LE (*int32val);
3955 align_pointer (meta->raw_metadata, p);
3956 int16val = (guint16*)p;
3957 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3958 *int16val = GUINT16_TO_LE (5); /* number of streams */
3962 * write the stream info.
3964 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3965 table_offset += 3; table_offset &= ~3;
3967 assembly->tstream.index = heapt_size;
3968 for (i = 0; i < 5; ++i) {
3969 int32val = (guint32*)p;
3970 stream_desc [i].stream->offset = table_offset;
3971 *int32val++ = GUINT32_TO_LE (table_offset);
3972 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3973 table_offset += GUINT32_FROM_LE (*int32val);
3974 table_offset += 3; table_offset &= ~3;
3976 strcpy ((char*)p, stream_desc [i].name);
3977 p += strlen (stream_desc [i].name) + 1;
3978 align_pointer (meta->raw_metadata, p);
3981 * now copy the data, the table stream header and contents goes first.
3983 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3984 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3985 int32val = (guint32*)p;
3986 *int32val = GUINT32_TO_LE (0); /* reserved */
3989 if (mono_framework_version () > 1) {
3990 *p++ = 2; /* version */
3993 *p++ = 1; /* version */
3997 if (meta->idx_string_wide)
3999 if (meta->idx_guid_wide)
4001 if (meta->idx_blob_wide)
4004 *p++ = 1; /* reserved */
4005 int64val = (guint64*)p;
4006 *int64val++ = GUINT64_TO_LE (valid_mask);
4007 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4009 int32val = (guint32*)p;
4010 for (i = 0; i < MONO_TABLE_NUM; i++){
4011 if (meta->tables [i].rows == 0)
4013 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4015 p = (unsigned char*)int32val;
4017 /* sort the tables that still need sorting */
4018 table = &assembly->tables [MONO_TABLE_CONSTANT];
4020 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4021 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4023 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4024 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4026 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4027 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4029 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4030 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4032 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4033 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4034 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4036 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4037 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4039 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4041 /* compress the tables */
4042 for (i = 0; i < MONO_TABLE_NUM; i++){
4045 guint32 bitfield = meta->tables [i].size_bitfield;
4046 if (!meta->tables [i].rows)
4048 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4049 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4050 meta->tables [i].base = (char*)p;
4051 for (row = 1; row <= meta->tables [i].rows; ++row) {
4052 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4053 for (col = 0; col < assembly->tables [i].columns; ++col) {
4054 switch (mono_metadata_table_size (bitfield, col)) {
4056 *p++ = values [col];
4059 *p++ = values [col] & 0xff;
4060 *p++ = (values [col] >> 8) & 0xff;
4063 *p++ = values [col] & 0xff;
4064 *p++ = (values [col] >> 8) & 0xff;
4065 *p++ = (values [col] >> 16) & 0xff;
4066 *p++ = (values [col] >> 24) & 0xff;
4069 g_assert_not_reached ();
4073 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4076 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4077 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4078 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4079 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4080 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4082 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4086 * Some tables in metadata need to be sorted according to some criteria, but
4087 * when methods and fields are first created with reflection, they may be assigned a token
4088 * that doesn't correspond to the final token they will get assigned after the sorting.
4089 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4090 * with the reflection objects that represent them. Once all the tables are set up, the
4091 * reflection objects will contains the correct table index. fixup_method() will fixup the
4092 * tokens for the method with ILGenerator @ilgen.
4095 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4097 guint32 code_idx = GPOINTER_TO_UINT (value);
4098 MonoReflectionILTokenInfo *iltoken;
4099 MonoReflectionFieldBuilder *field;
4100 MonoReflectionCtorBuilder *ctor;
4101 MonoReflectionMethodBuilder *method;
4102 MonoReflectionTypeBuilder *tb;
4103 MonoReflectionArrayMethod *am;
4105 unsigned char *target;
4107 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4108 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4109 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4110 switch (target [3]) {
4111 case MONO_TABLE_FIELD:
4112 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4113 field = (MonoReflectionFieldBuilder *)iltoken->member;
4114 idx = field->table_idx;
4115 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4116 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4117 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4119 g_assert_not_reached ();
4122 case MONO_TABLE_METHOD:
4123 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4124 method = (MonoReflectionMethodBuilder *)iltoken->member;
4125 idx = method->table_idx;
4126 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4127 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4128 idx = ctor->table_idx;
4129 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4130 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4131 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4132 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4134 g_assert_not_reached ();
4137 case MONO_TABLE_TYPEDEF:
4138 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4139 g_assert_not_reached ();
4140 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4141 idx = tb->table_idx;
4143 case MONO_TABLE_MEMBERREF:
4144 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4145 am = (MonoReflectionArrayMethod*)iltoken->member;
4146 idx = am->table_idx;
4147 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4148 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4149 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4150 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4151 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4152 g_assert (m->klass->generic_class || m->klass->generic_container);
4154 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4156 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4157 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4158 g_assert (is_field_on_inst (f));
4160 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4161 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4163 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4165 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4167 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4170 g_assert_not_reached ();
4173 case MONO_TABLE_METHODSPEC:
4174 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4175 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4176 g_assert (mono_method_signature (m)->generic_param_count);
4178 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4180 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4183 g_assert_not_reached ();
4187 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4189 target [0] = idx & 0xff;
4190 target [1] = (idx >> 8) & 0xff;
4191 target [2] = (idx >> 16) & 0xff;
4198 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4199 * value is not known when the table is emitted.
4202 fixup_cattrs (MonoDynamicImage *assembly)
4204 MonoDynamicTable *table;
4206 guint32 type, i, idx, token;
4209 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4211 for (i = 0; i < table->rows; ++i) {
4212 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4214 type = values [MONO_CUSTOM_ATTR_TYPE];
4215 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4216 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4217 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4218 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4221 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4222 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4223 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4224 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4231 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4233 MonoDynamicTable *table;
4236 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4238 alloc_table (table, table->rows);
4239 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4240 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4241 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4242 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4243 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4248 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4250 MonoDynamicTable *table;
4254 char *b = blob_size;
4256 guint32 idx, offset;
4258 if (rsrc->filename) {
4259 name = mono_string_to_utf8 (rsrc->filename);
4260 sname = g_path_get_basename (name);
4262 table = &assembly->tables [MONO_TABLE_FILE];
4264 alloc_table (table, table->rows);
4265 values = table->values + table->next_idx * MONO_FILE_SIZE;
4266 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4267 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4270 mono_sha1_get_digest_from_file (name, hash);
4271 mono_metadata_encode_value (20, b, &b);
4272 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4273 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4275 idx = table->next_idx++;
4277 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4283 data = mono_array_addr (rsrc->data, char, 0);
4284 len = mono_array_length (rsrc->data);
4290 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4291 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4292 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4293 mono_image_add_stream_data (&assembly->resources, data, len);
4297 * The entry should be emitted into the MANIFESTRESOURCE table of
4298 * the main module, but that needs to reference the FILE table
4299 * which isn't emitted yet.
4306 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4310 set_version_from_string (MonoString *version, guint32 *values)
4312 gchar *ver, *p, *str;
4315 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4316 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4317 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4318 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4321 ver = str = mono_string_to_utf8 (version);
4322 for (i = 0; i < 4; ++i) {
4323 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4329 /* handle Revision and Build */
4339 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4343 char *b = blob_size;
4348 len = mono_array_length (pkey);
4349 mono_metadata_encode_value (len, b, &b);
4350 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4351 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4353 assembly->public_key = g_malloc (len);
4354 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4355 assembly->public_key_len = len;
4357 /* Special case: check for ECMA key (16 bytes) */
4358 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4359 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4360 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4361 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4362 /* minimum key size (in 2.0) is 384 bits */
4363 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4365 /* FIXME - verifier */
4366 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4367 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4369 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4375 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4377 MonoDynamicTable *table;
4378 MonoDynamicImage *assembly;
4379 MonoReflectionAssemblyBuilder *assemblyb;
4383 guint32 module_index;
4385 assemblyb = moduleb->assemblyb;
4386 assembly = moduleb->dynamic_image;
4387 domain = mono_object_domain (assemblyb);
4389 /* Emit ASSEMBLY table */
4390 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4391 alloc_table (table, 1);
4392 values = table->values + MONO_ASSEMBLY_SIZE;
4393 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4394 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4395 if (assemblyb->culture) {
4396 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4398 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4400 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4401 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4402 set_version_from_string (assemblyb->version, values);
4404 /* Emit FILE + EXPORTED_TYPE table */
4406 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4408 MonoReflectionModuleBuilder *file_module =
4409 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4410 if (file_module != moduleb) {
4411 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4413 if (file_module->types) {
4414 for (j = 0; j < file_module->num_types; ++j) {
4415 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4416 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4421 if (assemblyb->loaded_modules) {
4422 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4423 MonoReflectionModule *file_module =
4424 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4425 mono_image_fill_file_table (domain, file_module, assembly);
4427 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4430 if (assemblyb->type_forwarders)
4431 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4433 /* Emit MANIFESTRESOURCE table */
4435 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4437 MonoReflectionModuleBuilder *file_module =
4438 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4439 /* The table for the main module is emitted later */
4440 if (file_module != moduleb) {
4442 if (file_module->resources) {
4443 int len = mono_array_length (file_module->resources);
4444 for (j = 0; j < len; ++j) {
4445 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4446 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4453 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4456 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4457 * for the modulebuilder @moduleb.
4458 * At the end of the process, method and field tokens are fixed up and the
4459 * on-disk compressed metadata representation is created.
4462 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4464 MonoDynamicTable *table;
4465 MonoDynamicImage *assembly;
4466 MonoReflectionAssemblyBuilder *assemblyb;
4472 assemblyb = moduleb->assemblyb;
4473 assembly = moduleb->dynamic_image;
4474 domain = mono_object_domain (assemblyb);
4476 if (assembly->text_rva)
4479 assembly->text_rva = START_TEXT_RVA;
4481 if (moduleb->is_main) {
4482 mono_image_emit_manifest (moduleb);
4485 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4486 table->rows = 1; /* .<Module> */
4488 alloc_table (table, table->rows);
4490 * Set the first entry.
4492 values = table->values + table->columns;
4493 values [MONO_TYPEDEF_FLAGS] = 0;
4494 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4495 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4496 values [MONO_TYPEDEF_EXTENDS] = 0;
4497 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4498 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4501 * handle global methods
4502 * FIXME: test what to do when global methods are defined in multiple modules.
4504 if (moduleb->global_methods) {
4505 table = &assembly->tables [MONO_TABLE_METHOD];
4506 table->rows += mono_array_length (moduleb->global_methods);
4507 alloc_table (table, table->rows);
4508 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4509 mono_image_get_method_info (
4510 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4512 if (moduleb->global_fields) {
4513 table = &assembly->tables [MONO_TABLE_FIELD];
4514 table->rows += mono_array_length (moduleb->global_fields);
4515 alloc_table (table, table->rows);
4516 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4517 mono_image_get_field_info (
4518 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4521 table = &assembly->tables [MONO_TABLE_MODULE];
4522 alloc_table (table, 1);
4523 mono_image_fill_module_table (domain, moduleb, assembly);
4525 /* Collect all types into a list sorted by their table_idx */
4526 types = g_ptr_array_new ();
4529 for (i = 0; i < moduleb->num_types; ++i) {
4530 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4531 collect_types (types, type);
4534 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4535 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4536 table->rows += types->len;
4537 alloc_table (table, table->rows);
4540 * Emit type names + namespaces at one place inside the string heap,
4541 * so load_class_names () needs to touch fewer pages.
4543 for (i = 0; i < types->len; ++i) {
4544 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4545 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4547 for (i = 0; i < types->len; ++i) {
4548 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4549 string_heap_insert_mstring (&assembly->sheap, tb->name);
4552 for (i = 0; i < types->len; ++i) {
4553 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4554 mono_image_get_type_info (domain, type, assembly);
4558 * table->rows is already set above and in mono_image_fill_module_table.
4560 /* add all the custom attributes at the end, once all the indexes are stable */
4561 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4563 /* CAS assembly permissions */
4564 if (assemblyb->permissions_minimum)
4565 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4566 if (assemblyb->permissions_optional)
4567 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4568 if (assemblyb->permissions_refused)
4569 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4571 module_add_cattrs (assembly, moduleb);
4574 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4576 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4577 * the final tokens and don't need another fixup pass. */
4579 if (moduleb->global_methods) {
4580 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4581 MonoReflectionMethodBuilder *mb = mono_array_get (
4582 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4583 mono_image_add_methodimpl (assembly, mb);
4587 for (i = 0; i < types->len; ++i) {
4588 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4589 if (type->methods) {
4590 for (j = 0; j < type->num_methods; ++j) {
4591 MonoReflectionMethodBuilder *mb = mono_array_get (
4592 type->methods, MonoReflectionMethodBuilder*, j);
4594 mono_image_add_methodimpl (assembly, mb);
4599 g_ptr_array_free (types, TRUE);
4601 fixup_cattrs (assembly);
4604 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4607 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4609 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4612 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4616 guint32 import_lookup_table;
4620 guint32 import_address_table_rva;
4628 #ifndef DISABLE_REFLECTION_EMIT
4631 * mono_image_insert_string:
4632 * @module: module builder object
4635 * Insert @str into the user string stream of @module.
4638 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4640 MonoDynamicImage *assembly;
4645 MONO_ARCH_SAVE_REGS;
4647 if (!module->dynamic_image)
4648 mono_image_module_basic_init (module);
4650 assembly = module->dynamic_image;
4652 if (assembly->save) {
4653 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4654 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4655 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4657 char *swapped = g_malloc (2 * mono_string_length (str));
4658 const char *p = (const char*)mono_string_chars (str);
4660 swap_with_size (swapped, p, 2, mono_string_length (str));
4661 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4665 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4667 mono_image_add_stream_data (&assembly->us, "", 1);
4669 idx = assembly->us.index ++;
4672 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4674 return MONO_TOKEN_STRING | idx;
4678 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4683 klass = obj->vtable->klass;
4684 if (strcmp (klass->name, "MonoMethod") == 0) {
4685 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4686 MonoMethodSignature *sig, *old;
4687 guint32 sig_token, parent;
4690 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4692 nargs = mono_array_length (opt_param_types);
4693 old = mono_method_signature (method);
4694 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4696 sig->hasthis = old->hasthis;
4697 sig->explicit_this = old->explicit_this;
4698 sig->call_convention = old->call_convention;
4699 sig->generic_param_count = old->generic_param_count;
4700 sig->param_count = old->param_count + nargs;
4701 sig->sentinelpos = old->param_count;
4702 sig->ret = old->ret;
4704 for (i = 0; i < old->param_count; i++)
4705 sig->params [i] = old->params [i];
4707 for (i = 0; i < nargs; i++) {
4708 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4709 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4712 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4713 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4714 parent >>= MONO_TYPEDEFORREF_BITS;
4716 parent <<= MONO_MEMBERREF_PARENT_BITS;
4717 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4719 sig_token = method_encode_signature (assembly, sig);
4720 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4721 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4722 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4723 ReflectionMethodBuilder rmb;
4724 guint32 parent, sig;
4727 reflection_methodbuilder_from_method_builder (&rmb, mb);
4728 rmb.opt_types = opt_param_types;
4730 sig = method_builder_encode_signature (assembly, &rmb);
4732 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4733 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4735 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4736 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4738 name = mono_string_to_utf8 (rmb.name);
4739 token = mono_image_get_varargs_method_token (
4740 assembly, parent, name, sig);
4743 g_error ("requested method token for %s\n", klass->name);
4750 * mono_image_create_token:
4751 * @assembly: a dynamic assembly
4753 * @register_token: Whenever to register the token in the assembly->tokens hash.
4755 * Get a token to insert in the IL code stream for the given MemberInfo.
4756 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4757 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4761 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4762 gboolean create_methodspec, gboolean register_token)
4767 klass = obj->vtable->klass;
4769 /* Check for user defined reflection objects */
4770 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4771 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4772 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4774 if (strcmp (klass->name, "MethodBuilder") == 0) {
4775 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4776 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4778 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4779 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4781 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4782 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4783 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4784 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4785 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4787 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4788 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4790 token = mono_image_get_ctorbuilder_token (assembly, mb);
4791 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4792 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4793 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4794 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4795 if (tb->generic_params) {
4796 token = mono_image_get_generic_field_token (assembly, fb);
4798 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4800 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4801 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4802 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4803 } else if (strcmp (klass->name, "MonoType") == 0) {
4804 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4805 MonoClass *mc = mono_class_from_mono_type (type);
4806 token = mono_metadata_token_from_dor (
4807 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4808 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4809 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4810 token = mono_metadata_token_from_dor (
4811 mono_image_typedef_or_ref (assembly, type));
4812 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4813 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4814 token = mono_metadata_token_from_dor (
4815 mono_image_typedef_or_ref (assembly, type));
4816 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4817 strcmp (klass->name, "MonoMethod") == 0 ||
4818 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4819 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4820 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4821 if (m->method->is_inflated) {
4822 if (create_methodspec)
4823 token = mono_image_get_methodspec_token (assembly, m->method);
4825 token = mono_image_get_inflated_method_token (assembly, m->method);
4826 } else if ((m->method->klass->image == &assembly->image) &&
4827 !m->method->klass->generic_class) {
4828 static guint32 method_table_idx = 0xffffff;
4829 if (m->method->klass->wastypebuilder) {
4830 /* we use the same token as the one that was assigned
4831 * to the Methodbuilder.
4832 * FIXME: do the equivalent for Fields.
4834 token = m->method->token;
4837 * Each token should have a unique index, but the indexes are
4838 * assigned by managed code, so we don't know about them. An
4839 * easy solution is to count backwards...
4841 method_table_idx --;
4842 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4845 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4847 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4848 } else if (strcmp (klass->name, "MonoField") == 0) {
4849 MonoReflectionField *f = (MonoReflectionField *)obj;
4850 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4851 static guint32 field_table_idx = 0xffffff;
4853 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4855 token = mono_image_get_fieldref_token (assembly, f);
4857 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4858 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4859 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4860 token = mono_image_get_array_token (assembly, m);
4861 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4862 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4863 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4864 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4865 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4866 token = mono_metadata_token_from_dor (
4867 mono_image_typedef_or_ref (assembly, type));
4868 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4869 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4870 token = mono_image_get_field_on_inst_token (assembly, f);
4871 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4872 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4873 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4874 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4875 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4876 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4877 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4878 MonoReflectionType *type = (MonoReflectionType *)obj;
4879 token = mono_metadata_token_from_dor (
4880 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4882 g_error ("requested token for %s\n", klass->name);
4886 mono_image_register_token (assembly, token, obj);
4892 * mono_image_register_token:
4894 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4895 * the Module.ResolveXXXToken () methods to work.
4898 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4900 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4902 /* There could be multiple MethodInfo objects with the same token */
4903 //g_assert (prev == obj);
4905 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4909 static MonoDynamicImage*
4910 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4912 static const guchar entrycode [16] = {0xff, 0x25, 0};
4913 MonoDynamicImage *image;
4916 const char *version;
4918 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4919 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4921 version = mono_get_runtime_info ()->runtime_version;
4924 image = GC_MALLOC (sizeof (MonoDynamicImage));
4926 image = g_new0 (MonoDynamicImage, 1);
4929 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4931 /*g_print ("created image %p\n", image);*/
4932 /* keep in sync with image.c */
4933 image->image.name = assembly_name;
4934 image->image.assembly_name = image->image.name; /* they may be different */
4935 image->image.module_name = module_name;
4936 image->image.version = g_strdup (version);
4937 image->image.md_version_major = 1;
4938 image->image.md_version_minor = 1;
4939 image->image.dynamic = TRUE;
4941 image->image.references = g_new0 (MonoAssembly*, 1);
4942 image->image.references [0] = NULL;
4944 mono_image_init (&image->image);
4946 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4947 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4948 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4949 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4950 image->handleref = g_hash_table_new (NULL, NULL);
4951 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4952 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4953 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4954 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4955 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4956 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4957 image->gen_params = g_ptr_array_new ();
4959 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4960 string_heap_init (&image->sheap);
4961 mono_image_add_stream_data (&image->us, "", 1);
4962 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4963 /* import tables... */
4964 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4965 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4966 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4967 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4968 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4969 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4970 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4971 stream_data_align (&image->code);
4973 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4975 for (i=0; i < MONO_TABLE_NUM; ++i) {
4976 image->tables [i].next_idx = 1;
4977 image->tables [i].columns = table_sizes [i];
4980 image->image.assembly = (MonoAssembly*)assembly;
4981 image->run = assembly->run;
4982 image->save = assembly->save;
4983 image->pe_kind = 0x1; /* ILOnly */
4984 image->machine = 0x14c; /* I386 */
4986 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4993 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4999 mono_dynamic_image_free (MonoDynamicImage *image)
5001 MonoDynamicImage *di = image;
5006 mono_g_hash_table_destroy (di->methodspec);
5008 g_hash_table_destroy (di->typespec);
5010 g_hash_table_destroy (di->typeref);
5012 g_hash_table_destroy (di->handleref);
5014 mono_g_hash_table_destroy (di->tokens);
5015 if (di->generic_def_objects)
5016 mono_g_hash_table_destroy (di->generic_def_objects);
5017 if (di->blob_cache) {
5018 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5019 g_hash_table_destroy (di->blob_cache);
5021 if (di->standalonesig_cache)
5022 g_hash_table_destroy (di->standalonesig_cache);
5023 for (list = di->array_methods; list; list = list->next) {
5024 ArrayMethod *am = (ArrayMethod *)list->data;
5029 g_list_free (di->array_methods);
5030 if (di->gen_params) {
5031 for (i = 0; i < di->gen_params->len; i++) {
5032 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5033 if (entry->gparam->type.type) {
5034 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5035 g_free ((char*)mono_generic_param_info (param)->name);
5038 mono_gc_deregister_root ((char*) &entry->gparam);
5041 g_ptr_array_free (di->gen_params, TRUE);
5043 if (di->token_fixups)
5044 mono_g_hash_table_destroy (di->token_fixups);
5045 if (di->method_to_table_idx)
5046 g_hash_table_destroy (di->method_to_table_idx);
5047 if (di->field_to_table_idx)
5048 g_hash_table_destroy (di->field_to_table_idx);
5049 if (di->method_aux_hash)
5050 g_hash_table_destroy (di->method_aux_hash);
5051 g_free (di->strong_name);
5052 g_free (di->win32_res);
5054 g_free (di->public_key);
5056 /*g_print ("string heap destroy for image %p\n", di);*/
5057 mono_dynamic_stream_reset (&di->sheap);
5058 mono_dynamic_stream_reset (&di->code);
5059 mono_dynamic_stream_reset (&di->resources);
5060 mono_dynamic_stream_reset (&di->us);
5061 mono_dynamic_stream_reset (&di->blob);
5062 mono_dynamic_stream_reset (&di->tstream);
5063 mono_dynamic_stream_reset (&di->guid);
5064 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5065 g_free (di->tables [i].values);
5069 #ifndef DISABLE_REFLECTION_EMIT
5072 * mono_image_basic_init:
5073 * @assembly: an assembly builder object
5075 * Create the MonoImage that represents the assembly builder and setup some
5076 * of the helper hash table and the basic metadata streams.
5079 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5081 MonoDynamicAssembly *assembly;
5082 MonoDynamicImage *image;
5083 MonoDomain *domain = mono_object_domain (assemblyb);
5085 MONO_ARCH_SAVE_REGS;
5087 if (assemblyb->dynamic_assembly)
5091 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5093 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5096 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5098 assembly->assembly.ref_count = 1;
5099 assembly->assembly.dynamic = TRUE;
5100 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5101 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5102 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5103 if (assemblyb->culture)
5104 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5106 assembly->assembly.aname.culture = g_strdup ("");
5108 if (assemblyb->version) {
5109 char *vstr = mono_string_to_utf8 (assemblyb->version);
5110 char **version = g_strsplit (vstr, ".", 4);
5111 char **parts = version;
5112 assembly->assembly.aname.major = atoi (*parts++);
5113 assembly->assembly.aname.minor = atoi (*parts++);
5114 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5115 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5117 g_strfreev (version);
5120 assembly->assembly.aname.major = 0;
5121 assembly->assembly.aname.minor = 0;
5122 assembly->assembly.aname.build = 0;
5123 assembly->assembly.aname.revision = 0;
5126 assembly->run = assemblyb->access != 2;
5127 assembly->save = assemblyb->access != 1;
5129 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5130 image->initial_image = TRUE;
5131 assembly->assembly.aname.name = image->image.name;
5132 assembly->assembly.image = &image->image;
5133 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5134 /* -1 to correct for the trailing NULL byte */
5135 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5136 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5138 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5141 mono_domain_assemblies_lock (domain);
5142 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5143 mono_domain_assemblies_unlock (domain);
5145 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5147 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5149 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5152 #endif /* !DISABLE_REFLECTION_EMIT */
5154 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5157 calc_section_size (MonoDynamicImage *assembly)
5161 /* alignment constraints */
5162 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5163 g_assert ((assembly->code.index % 4) == 0);
5164 assembly->meta_size += 3;
5165 assembly->meta_size &= ~3;
5166 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5167 g_assert ((assembly->resources.index % 4) == 0);
5169 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5170 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5173 if (assembly->win32_res) {
5174 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5176 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5177 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5181 assembly->sections [MONO_SECTION_RELOC].size = 12;
5182 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5192 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5196 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5198 ResTreeNode *t1 = (ResTreeNode*)a;
5199 ResTreeNode *t2 = (ResTreeNode*)b;
5201 return t1->id - t2->id;
5205 * resource_tree_create:
5207 * Organize the resources into a resource tree.
5209 static ResTreeNode *
5210 resource_tree_create (MonoArray *win32_resources)
5212 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5216 tree = g_new0 (ResTreeNode, 1);
5218 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5219 MonoReflectionWin32Resource *win32_res =
5220 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5224 /* FIXME: BUG: this stores managed references in unmanaged memory */
5225 lang_node = g_new0 (ResTreeNode, 1);
5226 lang_node->id = win32_res->lang_id;
5227 lang_node->win32_res = win32_res;
5229 /* Create type node if neccesary */
5231 for (l = tree->children; l; l = l->next)
5232 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5233 type_node = (ResTreeNode*)l->data;
5238 type_node = g_new0 (ResTreeNode, 1);
5239 type_node->id = win32_res->res_type;
5242 * The resource types have to be sorted otherwise
5243 * Windows Explorer can't display the version information.
5245 tree->children = g_slist_insert_sorted (tree->children,
5246 type_node, resource_tree_compare_by_id);
5249 /* Create res node if neccesary */
5251 for (l = type_node->children; l; l = l->next)
5252 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5253 res_node = (ResTreeNode*)l->data;
5258 res_node = g_new0 (ResTreeNode, 1);
5259 res_node->id = win32_res->res_id;
5260 type_node->children = g_slist_append (type_node->children, res_node);
5263 res_node->children = g_slist_append (res_node->children, lang_node);
5270 * resource_tree_encode:
5272 * Encode the resource tree into the format used in the PE file.
5275 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5278 MonoPEResourceDir dir;
5279 MonoPEResourceDirEntry dir_entry;
5280 MonoPEResourceDataEntry data_entry;
5282 guint32 res_id_entries;
5285 * For the format of the resource directory, see the article
5286 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5290 memset (&dir, 0, sizeof (dir));
5291 memset (&dir_entry, 0, sizeof (dir_entry));
5292 memset (&data_entry, 0, sizeof (data_entry));
5294 g_assert (sizeof (dir) == 16);
5295 g_assert (sizeof (dir_entry) == 8);
5296 g_assert (sizeof (data_entry) == 16);
5298 node->offset = p - begin;
5300 /* IMAGE_RESOURCE_DIRECTORY */
5301 res_id_entries = g_slist_length (node->children);
5302 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5304 memcpy (p, &dir, sizeof (dir));
5307 /* Reserve space for entries */
5309 p += sizeof (dir_entry) * res_id_entries;
5311 /* Write children */
5312 for (l = node->children; l; l = l->next) {
5313 ResTreeNode *child = (ResTreeNode*)l->data;
5315 if (child->win32_res) {
5318 child->offset = p - begin;
5320 /* IMAGE_RESOURCE_DATA_ENTRY */
5321 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5322 size = mono_array_length (child->win32_res->res_data);
5323 data_entry.rde_size = GUINT32_TO_LE (size);
5325 memcpy (p, &data_entry, sizeof (data_entry));
5326 p += sizeof (data_entry);
5328 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5331 resource_tree_encode (child, begin, p, &p);
5335 /* IMAGE_RESOURCE_ENTRY */
5336 for (l = node->children; l; l = l->next) {
5337 ResTreeNode *child = (ResTreeNode*)l->data;
5339 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5340 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5342 memcpy (entries, &dir_entry, sizeof (dir_entry));
5343 entries += sizeof (dir_entry);
5350 resource_tree_free (ResTreeNode * node)
5353 for (list = node->children; list; list = list->next)
5354 resource_tree_free ((ResTreeNode*)list->data);
5355 g_slist_free(node->children);
5360 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5365 MonoReflectionWin32Resource *win32_res;
5368 if (!assemblyb->win32_resources)
5372 * Resources are stored in a three level tree inside the PE file.
5373 * - level one contains a node for each type of resource
5374 * - level two contains a node for each resource
5375 * - level three contains a node for each instance of a resource for a
5376 * specific language.
5379 tree = resource_tree_create (assemblyb->win32_resources);
5381 /* Estimate the size of the encoded tree */
5383 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5384 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5385 size += mono_array_length (win32_res->res_data);
5387 /* Directory structure */
5388 size += mono_array_length (assemblyb->win32_resources) * 256;
5389 p = buf = g_malloc (size);
5391 resource_tree_encode (tree, p, p, &p);
5393 g_assert (p - buf <= size);
5395 assembly->win32_res = g_malloc (p - buf);
5396 assembly->win32_res_size = p - buf;
5397 memcpy (assembly->win32_res, buf, p - buf);
5400 resource_tree_free (tree);
5404 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5406 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5409 p += sizeof (MonoPEResourceDir);
5410 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5411 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5412 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5413 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5414 fixup_resource_directory (res_section, child, rva);
5416 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5417 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5420 p += sizeof (MonoPEResourceDirEntry);
5425 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5428 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5429 g_error ("WriteFile returned %d\n", GetLastError ());
5433 * mono_image_create_pefile:
5434 * @mb: a module builder object
5436 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5437 * assembly->pefile where it can be easily retrieved later in chunks.
5440 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5442 MonoMSDOSHeader *msdos;
5443 MonoDotNetHeader *header;
5444 MonoSectionTable *section;
5445 MonoCLIHeader *cli_header;
5446 guint32 size, image_size, virtual_base, text_offset;
5447 guint32 header_start, section_start, file_offset, virtual_offset;
5448 MonoDynamicImage *assembly;
5449 MonoReflectionAssemblyBuilder *assemblyb;
5450 MonoDynamicStream pefile_stream = {0};
5451 MonoDynamicStream *pefile = &pefile_stream;
5453 guint32 *rva, value;
5455 static const unsigned char msheader[] = {
5456 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5457 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5460 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5461 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5462 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5463 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5466 assemblyb = mb->assemblyb;
5468 mono_image_basic_init (assemblyb);
5469 assembly = mb->dynamic_image;
5471 assembly->pe_kind = assemblyb->pe_kind;
5472 assembly->machine = assemblyb->machine;
5473 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5474 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5476 mono_image_build_metadata (mb);
5478 if (mb->is_main && assemblyb->resources) {
5479 int len = mono_array_length (assemblyb->resources);
5480 for (i = 0; i < len; ++i)
5481 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5484 if (mb->resources) {
5485 int len = mono_array_length (mb->resources);
5486 for (i = 0; i < len; ++i)
5487 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5490 build_compressed_metadata (assembly);
5493 assembly_add_win32_resources (assembly, assemblyb);
5495 nsections = calc_section_size (assembly);
5497 /* The DOS header and stub */
5498 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5499 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5501 /* the dotnet header */
5502 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5504 /* the section tables */
5505 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5507 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5508 virtual_offset = VIRT_ALIGN;
5511 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5512 if (!assembly->sections [i].size)
5515 file_offset += FILE_ALIGN - 1;
5516 file_offset &= ~(FILE_ALIGN - 1);
5517 virtual_offset += VIRT_ALIGN - 1;
5518 virtual_offset &= ~(VIRT_ALIGN - 1);
5520 assembly->sections [i].offset = file_offset;
5521 assembly->sections [i].rva = virtual_offset;
5523 file_offset += assembly->sections [i].size;
5524 virtual_offset += assembly->sections [i].size;
5525 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5528 file_offset += FILE_ALIGN - 1;
5529 file_offset &= ~(FILE_ALIGN - 1);
5531 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5533 /* back-patch info */
5534 msdos = (MonoMSDOSHeader*)pefile->data;
5535 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5537 header = (MonoDotNetHeader*)(pefile->data + header_start);
5538 header->pesig [0] = 'P';
5539 header->pesig [1] = 'E';
5541 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5542 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5543 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5544 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5545 if (assemblyb->pekind == 1) {
5547 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5550 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5553 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5555 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5556 header->pe.pe_major = 6;
5557 header->pe.pe_minor = 0;
5558 size = assembly->sections [MONO_SECTION_TEXT].size;
5559 size += FILE_ALIGN - 1;
5560 size &= ~(FILE_ALIGN - 1);
5561 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5562 size = assembly->sections [MONO_SECTION_RSRC].size;
5563 size += FILE_ALIGN - 1;
5564 size &= ~(FILE_ALIGN - 1);
5565 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5566 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5567 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5568 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5569 /* pe_rva_entry_point always at the beginning of the text section */
5570 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5572 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5573 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5574 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5575 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5576 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5577 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5578 size = section_start;
5579 size += FILE_ALIGN - 1;
5580 size &= ~(FILE_ALIGN - 1);
5581 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5583 size += VIRT_ALIGN - 1;
5584 size &= ~(VIRT_ALIGN - 1);
5585 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5588 // Translate the PEFileKind value to the value expected by the Windows loader
5594 // PEFileKinds.Dll == 1
5595 // PEFileKinds.ConsoleApplication == 2
5596 // PEFileKinds.WindowApplication == 3
5599 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5600 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5602 if (assemblyb->pekind == 3)
5607 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5609 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5610 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5611 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5612 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5613 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5614 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5616 /* fill data directory entries */
5618 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5619 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5621 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5622 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5624 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5625 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5626 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5627 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5628 /* patch entrypoint name */
5629 if (assemblyb->pekind == 1)
5630 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5632 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5633 /* patch imported function RVA name */
5634 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5635 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5637 /* the import table */
5638 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5639 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5640 /* patch imported dll RVA name and other entries in the dir */
5641 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5642 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5643 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5644 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5645 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5646 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5648 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5649 value = (assembly->text_rva + assembly->imp_names_offset);
5650 *p++ = (value) & 0xff;
5651 *p++ = (value >> 8) & (0xff);
5652 *p++ = (value >> 16) & (0xff);
5653 *p++ = (value >> 24) & (0xff);
5655 /* the CLI header info */
5656 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5657 cli_header->ch_size = GUINT32_FROM_LE (72);
5658 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5659 if (mono_framework_version () > 1)
5660 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5662 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5663 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5664 if (assemblyb->entry_point) {
5665 guint32 table_idx = 0;
5666 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5667 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5668 table_idx = methodb->table_idx;
5670 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5672 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5674 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5676 /* The embedded managed resources */
5677 text_offset = assembly->text_rva + assembly->code.index;
5678 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5679 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5680 text_offset += assembly->resources.index;
5681 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5682 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5683 text_offset += assembly->meta_size;
5684 if (assembly->strong_name_size) {
5685 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5686 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5687 text_offset += assembly->strong_name_size;
5690 /* write the section tables and section content */
5691 section = (MonoSectionTable*)(pefile->data + section_start);
5692 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5693 static const char section_names [][7] = {
5694 ".text", ".rsrc", ".reloc"
5696 if (!assembly->sections [i].size)
5698 strcpy (section->st_name, section_names [i]);
5699 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5700 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5701 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5702 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5703 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5704 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5705 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5709 checked_write_file (file, pefile->data, pefile->index);
5711 mono_dynamic_stream_reset (pefile);
5713 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5714 if (!assembly->sections [i].size)
5717 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5718 g_error ("SetFilePointer returned %d\n", GetLastError ());
5721 case MONO_SECTION_TEXT:
5722 /* patch entry point */
5723 p = (guchar*)(assembly->code.data + 2);
5724 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5725 *p++ = (value) & 0xff;
5726 *p++ = (value >> 8) & 0xff;
5727 *p++ = (value >> 16) & 0xff;
5728 *p++ = (value >> 24) & 0xff;
5730 checked_write_file (file, assembly->code.data, assembly->code.index);
5731 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5732 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5733 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5736 g_free (assembly->image.raw_metadata);
5738 case MONO_SECTION_RELOC: {
5742 guint16 type_and_offset;
5746 g_assert (sizeof (reloc) == 12);
5748 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5749 reloc.block_size = GUINT32_FROM_LE (12);
5752 * the entrypoint is always at the start of the text section
5753 * 3 is IMAGE_REL_BASED_HIGHLOW
5754 * 2 is patch_size_rva - text_rva
5756 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5759 checked_write_file (file, &reloc, sizeof (reloc));
5763 case MONO_SECTION_RSRC:
5764 if (assembly->win32_res) {
5766 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5767 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5768 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5772 g_assert_not_reached ();
5776 /* check that the file is properly padded */
5777 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5778 g_error ("SetFilePointer returned %d\n", GetLastError ());
5779 if (! SetEndOfFile (file))
5780 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5782 mono_dynamic_stream_reset (&assembly->code);
5783 mono_dynamic_stream_reset (&assembly->us);
5784 mono_dynamic_stream_reset (&assembly->blob);
5785 mono_dynamic_stream_reset (&assembly->guid);
5786 mono_dynamic_stream_reset (&assembly->sheap);
5788 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5789 g_hash_table_destroy (assembly->blob_cache);
5790 assembly->blob_cache = NULL;
5793 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5796 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5798 g_assert_not_reached ();
5801 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5803 #ifndef DISABLE_REFLECTION_EMIT
5805 MonoReflectionModule *
5806 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5810 MonoImageOpenStatus status;
5811 MonoDynamicAssembly *assembly;
5812 guint32 module_count;
5813 MonoImage **new_modules;
5814 gboolean *new_modules_loaded;
5816 name = mono_string_to_utf8 (fileName);
5818 image = mono_image_open (name, &status);
5821 if (status == MONO_IMAGE_ERROR_ERRNO)
5822 exc = mono_get_exception_file_not_found (fileName);
5824 exc = mono_get_exception_bad_image_format (name);
5826 mono_raise_exception (exc);
5831 assembly = ab->dynamic_assembly;
5832 image->assembly = (MonoAssembly*)assembly;
5834 module_count = image->assembly->image->module_count;
5835 new_modules = g_new0 (MonoImage *, module_count + 1);
5836 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5838 if (image->assembly->image->modules)
5839 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5840 if (image->assembly->image->modules_loaded)
5841 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5842 new_modules [module_count] = image;
5843 new_modules_loaded [module_count] = TRUE;
5844 mono_image_addref (image);
5846 g_free (image->assembly->image->modules);
5847 image->assembly->image->modules = new_modules;
5848 image->assembly->image->modules_loaded = new_modules_loaded;
5849 image->assembly->image->module_count ++;
5851 mono_assembly_load_references (image, &status);
5853 mono_image_close (image);
5854 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5857 return mono_module_get_object (mono_domain_get (), image);
5860 #endif /* DISABLE_REFLECTION_EMIT */
5863 * We need to return always the same object for MethodInfo, FieldInfo etc..
5864 * but we need to consider the reflected type.
5865 * type uses a different hash, since it uses custom hash/equal functions.
5870 MonoClass *refclass;
5874 reflected_equal (gconstpointer a, gconstpointer b) {
5875 const ReflectedEntry *ea = a;
5876 const ReflectedEntry *eb = b;
5878 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5882 reflected_hash (gconstpointer a) {
5883 const ReflectedEntry *ea = a;
5884 return mono_aligned_addr_hash (ea->item);
5887 #define CHECK_OBJECT(t,p,k) \
5893 mono_domain_lock (domain); \
5894 if (!domain->refobject_hash) \
5895 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5896 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5897 mono_domain_unlock (domain); \
5900 mono_domain_unlock (domain); \
5903 #ifdef HAVE_BOEHM_GC
5904 /* ReflectedEntry doesn't need to be GC tracked */
5905 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5906 #define FREE_REFENTRY(entry) g_free ((entry))
5907 #define REFENTRY_REQUIRES_CLEANUP
5909 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5911 #define FREE_REFENTRY(entry)
5914 #define CACHE_OBJECT(t,p,o,k) \
5917 ReflectedEntry pe; \
5919 pe.refclass = (k); \
5920 mono_domain_lock (domain); \
5921 if (!domain->refobject_hash) \
5922 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5923 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5925 ReflectedEntry *e = ALLOC_REFENTRY; \
5927 e->refclass = (k); \
5928 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5931 mono_domain_unlock (domain); \
5936 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5938 mono_domain_lock (domain);
5939 if (domain->refobject_hash) {
5941 gpointer orig_pe, orig_value;
5944 pe.refclass = klass;
5945 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5946 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5947 FREE_REFENTRY (orig_pe);
5950 mono_domain_unlock (domain);
5953 #ifdef REFENTRY_REQUIRES_CLEANUP
5955 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5957 FREE_REFENTRY (key);
5962 mono_reflection_cleanup_domain (MonoDomain *domain)
5964 if (domain->refobject_hash) {
5965 /*let's avoid scanning the whole hashtable if not needed*/
5966 #ifdef REFENTRY_REQUIRES_CLEANUP
5967 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5969 mono_g_hash_table_destroy (domain->refobject_hash);
5970 domain->refobject_hash = NULL;
5974 #ifndef DISABLE_REFLECTION_EMIT
5976 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5978 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5982 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5984 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5988 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5990 MonoDynamicImage *image = moduleb->dynamic_image;
5991 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5995 MonoImage **new_modules;
5997 char *name, *fqname;
5999 * FIXME: we already created an image in mono_image_basic_init (), but
6000 * we don't know which module it belongs to, since that is only
6001 * determined at assembly save time.
6003 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6004 name = mono_string_to_utf8 (ab->name);
6005 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6006 if (!mono_error_ok (&error)) {
6008 mono_error_raise_exception (&error);
6010 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6012 moduleb->module.image = &image->image;
6013 moduleb->dynamic_image = image;
6014 register_module (mono_object_domain (moduleb), moduleb, image);
6016 /* register the module with the assembly */
6017 ass = ab->dynamic_assembly->assembly.image;
6018 module_count = ass->module_count;
6019 new_modules = g_new0 (MonoImage *, module_count + 1);
6022 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6023 new_modules [module_count] = &image->image;
6024 mono_image_addref (&image->image);
6026 g_free (ass->modules);
6027 ass->modules = new_modules;
6028 ass->module_count ++;
6033 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6035 MonoDynamicImage *image = moduleb->dynamic_image;
6037 g_assert (type->type);
6038 image->wrappers_type = mono_class_from_mono_type (type->type);
6044 * mono_assembly_get_object:
6045 * @domain: an app domain
6046 * @assembly: an assembly
6048 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6050 MonoReflectionAssembly*
6051 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6053 static MonoClass *System_Reflection_Assembly;
6054 MonoReflectionAssembly *res;
6056 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6057 if (!System_Reflection_Assembly)
6058 System_Reflection_Assembly = mono_class_from_name (
6059 mono_defaults.corlib, "System.Reflection", "Assembly");
6060 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
6061 res->assembly = assembly;
6063 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6068 MonoReflectionModule*
6069 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6071 static MonoClass *System_Reflection_Module;
6072 MonoReflectionModule *res;
6075 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6076 if (!System_Reflection_Module)
6077 System_Reflection_Module = mono_class_from_name (
6078 mono_defaults.corlib, "System.Reflection", "Module");
6079 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6082 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6084 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6085 basename = g_path_get_basename (image->name);
6086 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6087 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6091 if (image->assembly->image == image) {
6092 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6096 if (image->assembly->image->modules) {
6097 for (i = 0; i < image->assembly->image->module_count; i++) {
6098 if (image->assembly->image->modules [i] == image)
6099 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6101 g_assert (res->token);
6105 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6108 MonoReflectionModule*
6109 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6111 static MonoClass *System_Reflection_Module;
6112 MonoReflectionModule *res;
6113 MonoTableInfo *table;
6114 guint32 cols [MONO_FILE_SIZE];
6116 guint32 i, name_idx;
6119 if (!System_Reflection_Module)
6120 System_Reflection_Module = mono_class_from_name (
6121 mono_defaults.corlib, "System.Reflection", "Module");
6122 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6124 table = &image->tables [MONO_TABLE_FILE];
6125 g_assert (table_index < table->rows);
6126 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6129 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6130 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6132 /* Check whenever the row has a corresponding row in the moduleref table */
6133 table = &image->tables [MONO_TABLE_MODULEREF];
6134 for (i = 0; i < table->rows; ++i) {
6135 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6136 val = mono_metadata_string_heap (image, name_idx);
6137 if (strcmp (val, name) == 0)
6138 res->image = image->modules [i];
6141 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6142 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6143 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6144 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6145 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6151 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6153 if ((t1->type != t2->type) ||
6154 (t1->byref != t2->byref))
6158 case MONO_TYPE_VOID:
6159 case MONO_TYPE_BOOLEAN:
6160 case MONO_TYPE_CHAR:
6171 case MONO_TYPE_STRING:
6174 case MONO_TYPE_OBJECT:
6175 case MONO_TYPE_TYPEDBYREF:
6177 case MONO_TYPE_VALUETYPE:
6178 case MONO_TYPE_CLASS:
6179 case MONO_TYPE_SZARRAY:
6180 return t1->data.klass == t2->data.klass;
6182 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6183 case MONO_TYPE_ARRAY:
6184 if (t1->data.array->rank != t2->data.array->rank)
6186 return t1->data.array->eklass == t2->data.array->eklass;
6187 case MONO_TYPE_GENERICINST: {
6189 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6190 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6191 if (i1->type_argc != i2->type_argc)
6193 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6194 &t2->data.generic_class->container_class->byval_arg))
6196 /* FIXME: we should probably just compare the instance pointers directly. */
6197 for (i = 0; i < i1->type_argc; ++i) {
6198 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6204 case MONO_TYPE_MVAR:
6205 return t1->data.generic_param == t2->data.generic_param;
6207 g_error ("implement type compare for %0x!", t1->type);
6215 mymono_metadata_type_hash (MonoType *t1)
6221 hash |= t1->byref << 6; /* do not collide with t1->type values */
6223 case MONO_TYPE_VALUETYPE:
6224 case MONO_TYPE_CLASS:
6225 case MONO_TYPE_SZARRAY:
6226 /* check if the distribution is good enough */
6227 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6229 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6230 case MONO_TYPE_GENERICINST: {
6232 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6233 hash += g_str_hash (t1->data.generic_class->container_class->name);
6235 for (i = 0; i < inst->type_argc; ++i) {
6236 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6245 static MonoReflectionGenericClass*
6246 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6248 static MonoClass *System_Reflection_MonoGenericClass;
6249 MonoReflectionGenericClass *res;
6250 MonoClass *klass, *gklass;
6251 MonoGenericInst *ginst;
6252 MonoArray *type_args;
6256 /*This will only be fixed once we do full managed inflate of system types*/
6257 /*g_assert (!geninst->byref);*/
6259 if (!System_Reflection_MonoGenericClass) {
6260 System_Reflection_MonoGenericClass = mono_class_from_name (
6261 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6262 g_assert (System_Reflection_MonoGenericClass);
6265 klass = mono_class_from_mono_type (geninst);
6266 gklass = klass->generic_class->container_class;
6268 mono_class_init (klass);
6271 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6273 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6276 res->type.type = geninst;
6277 g_assert (gklass->reflection_info);
6278 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6279 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6281 ginst = klass->generic_class->context.class_inst;
6282 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6283 for (i = 0; i < ginst->type_argc; ++i)
6284 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6285 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6291 verify_safe_for_managed_space (MonoType *type)
6293 switch (type->type) {
6295 case MONO_TYPE_ARRAY:
6296 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6298 return verify_safe_for_managed_space (type->data.type);
6299 case MONO_TYPE_SZARRAY:
6300 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6301 case MONO_TYPE_GENERICINST: {
6302 MonoGenericInst *inst = type->data.generic_class->inst;
6306 for (i = 0; i < inst->type_argc; ++i)
6307 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6313 case MONO_TYPE_MVAR:
6320 * mono_type_get_object:
6321 * @domain: an app domain
6324 * Return an System.MonoType object representing the type @type.
6327 mono_type_get_object (MonoDomain *domain, MonoType *type)
6329 MonoReflectionType *res;
6330 MonoClass *klass = mono_class_from_mono_type (type);
6332 /*we must avoid using @type as it might have come
6333 * from a mono_metadata_type_dup and the caller
6334 * expects that is can be freed.
6335 * Using the right type from
6337 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6339 /* void is very common */
6340 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6341 return (MonoReflectionType*)domain->typeof_void;
6344 * If the vtable of the given class was already created, we can use
6345 * the MonoType from there and avoid all locking and hash table lookups.
6347 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6348 * that the resulting object is different.
6350 if (type == &klass->byval_arg && !klass->image->dynamic) {
6351 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6352 if (vtable && vtable->type)
6353 return vtable->type;
6356 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6357 mono_domain_lock (domain);
6358 if (!domain->type_hash)
6359 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6360 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6361 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6362 mono_domain_unlock (domain);
6363 mono_loader_unlock ();
6366 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6367 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6368 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6369 mono_g_hash_table_insert (domain->type_hash, type, res);
6370 mono_domain_unlock (domain);
6371 mono_loader_unlock ();
6375 if (!verify_safe_for_managed_space (type)) {
6376 mono_domain_unlock (domain);
6377 mono_loader_unlock ();
6378 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6381 if (klass->reflection_info && !klass->wastypebuilder) {
6382 /* g_assert_not_reached (); */
6383 /* should this be considered an error condition? */
6385 mono_domain_unlock (domain);
6386 mono_loader_unlock ();
6387 return klass->reflection_info;
6390 // FIXME: Get rid of this, do it in the icalls for Type
6391 mono_class_init (klass);
6393 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6395 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6398 mono_g_hash_table_insert (domain->type_hash, type, res);
6400 if (type->type == MONO_TYPE_VOID)
6401 domain->typeof_void = (MonoObject*)res;
6403 mono_domain_unlock (domain);
6404 mono_loader_unlock ();
6409 * mono_method_get_object:
6410 * @domain: an app domain
6412 * @refclass: the reflected type (can be NULL)
6414 * Return an System.Reflection.MonoMethod object representing the method @method.
6416 MonoReflectionMethod*
6417 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6420 * We use the same C representation for methods and constructors, but the type
6421 * name in C# is different.
6423 static MonoClass *System_Reflection_MonoMethod = NULL;
6424 static MonoClass *System_Reflection_MonoCMethod = NULL;
6425 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6426 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6428 MonoReflectionMethod *ret;
6430 if (method->is_inflated) {
6431 MonoReflectionGenericMethod *gret;
6433 refclass = method->klass;
6434 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6435 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6436 if (!System_Reflection_MonoGenericCMethod)
6437 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6438 klass = System_Reflection_MonoGenericCMethod;
6440 if (!System_Reflection_MonoGenericMethod)
6441 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6442 klass = System_Reflection_MonoGenericMethod;
6444 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6445 gret->method.method = method;
6446 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6447 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6448 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6452 refclass = method->klass;
6454 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6455 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6456 if (!System_Reflection_MonoCMethod)
6457 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6458 klass = System_Reflection_MonoCMethod;
6461 if (!System_Reflection_MonoMethod)
6462 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6463 klass = System_Reflection_MonoMethod;
6465 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6466 ret->method = method;
6467 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6468 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6472 * mono_method_clear_object:
6474 * Clear the cached reflection objects for the dynamic method METHOD.
6477 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6480 g_assert (method->dynamic);
6482 klass = method->klass;
6484 clear_cached_object (domain, method, klass);
6485 klass = klass->parent;
6487 /* Added by mono_param_get_objects () */
6488 clear_cached_object (domain, &(method->signature), NULL);
6489 klass = method->klass;
6491 clear_cached_object (domain, &(method->signature), klass);
6492 klass = klass->parent;
6497 * mono_field_get_object:
6498 * @domain: an app domain
6502 * Return an System.Reflection.MonoField object representing the field @field
6505 MonoReflectionField*
6506 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6508 MonoReflectionField *res;
6509 static MonoClass *monofield_klass;
6511 CHECK_OBJECT (MonoReflectionField *, field, klass);
6512 if (!monofield_klass)
6513 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6514 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6517 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6518 if (is_field_on_inst (field))
6519 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6521 res->attrs = field->type->attrs;
6522 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6523 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6527 * mono_property_get_object:
6528 * @domain: an app domain
6530 * @property: a property
6532 * Return an System.Reflection.MonoProperty object representing the property @property
6535 MonoReflectionProperty*
6536 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6538 MonoReflectionProperty *res;
6539 static MonoClass *monoproperty_klass;
6541 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6542 if (!monoproperty_klass)
6543 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6544 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6546 res->property = property;
6547 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6551 * mono_event_get_object:
6552 * @domain: an app domain
6556 * Return an System.Reflection.MonoEvent object representing the event @event
6559 MonoReflectionEvent*
6560 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6562 MonoReflectionEvent *res;
6563 MonoReflectionMonoEvent *mono_event;
6564 static MonoClass *monoevent_klass;
6566 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6567 if (!monoevent_klass)
6568 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6569 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6570 mono_event->klass = klass;
6571 mono_event->event = event;
6572 res = (MonoReflectionEvent*)mono_event;
6573 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6577 * mono_get_reflection_missing_object:
6578 * @domain: Domain where the object lives
6580 * Returns the System.Reflection.Missing.Value singleton object
6581 * (of type System.Reflection.Missing).
6583 * Used as the value for ParameterInfo.DefaultValue when Optional
6587 mono_get_reflection_missing_object (MonoDomain *domain)
6590 static MonoClassField *missing_value_field = NULL;
6592 if (!missing_value_field) {
6593 MonoClass *missing_klass;
6594 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6595 mono_class_init (missing_klass);
6596 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6597 g_assert (missing_value_field);
6599 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6605 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6608 *dbnull = mono_get_dbnull_object (domain);
6613 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6615 if (!*reflection_missing)
6616 *reflection_missing = mono_get_reflection_missing_object (domain);
6617 return *reflection_missing;
6621 * mono_param_get_objects:
6622 * @domain: an app domain
6625 * Return an System.Reflection.ParameterInfo array object representing the parameters
6626 * in the method @method.
6629 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6631 static MonoClass *System_Reflection_ParameterInfo;
6632 static MonoClass *System_Reflection_ParameterInfo_array;
6633 MonoArray *res = NULL;
6634 MonoReflectionMethod *member = NULL;
6635 MonoReflectionParameter *param = NULL;
6636 char **names, **blobs = NULL;
6637 guint32 *types = NULL;
6638 MonoType *type = NULL;
6639 MonoObject *dbnull = NULL;
6640 MonoObject *missing = NULL;
6641 MonoMarshalSpec **mspecs;
6642 MonoMethodSignature *sig;
6643 MonoVTable *pinfo_vtable;
6646 if (!System_Reflection_ParameterInfo_array) {
6649 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6650 mono_memory_barrier ();
6651 System_Reflection_ParameterInfo = klass;
6653 klass = mono_array_class_get (klass, 1);
6654 mono_memory_barrier ();
6655 System_Reflection_ParameterInfo_array = klass;
6658 if (!mono_method_signature (method)->param_count)
6659 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6661 /* Note: the cache is based on the address of the signature into the method
6662 * since we already cache MethodInfos with the method as keys.
6664 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6666 sig = mono_method_signature (method);
6667 member = mono_method_get_object (domain, method, refclass);
6668 names = g_new (char *, sig->param_count);
6669 mono_method_get_param_names (method, (const char **) names);
6671 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6672 mono_method_get_marshal_info (method, mspecs);
6674 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6675 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6676 for (i = 0; i < sig->param_count; ++i) {
6677 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6678 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6679 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6680 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6681 param->PositionImpl = i;
6682 param->AttrsImpl = sig->params [i]->attrs;
6684 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6685 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6686 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6688 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6692 blobs = g_new0 (char *, sig->param_count);
6693 types = g_new0 (guint32, sig->param_count);
6694 get_default_param_value_blobs (method, blobs, types);
6697 /* Build MonoType for the type from the Constant Table */
6699 type = g_new0 (MonoType, 1);
6700 type->type = types [i];
6701 type->data.klass = NULL;
6702 if (types [i] == MONO_TYPE_CLASS)
6703 type->data.klass = mono_defaults.object_class;
6704 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6705 /* For enums, types [i] contains the base type */
6707 type->type = MONO_TYPE_VALUETYPE;
6708 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6710 type->data.klass = mono_class_from_mono_type (type);
6712 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6714 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6715 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6716 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6717 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6719 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6725 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6727 mono_array_setref (res, i, param);
6734 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6736 mono_metadata_free_marshal_spec (mspecs [i]);
6739 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6743 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6745 return mono_param_get_objects_internal (domain, method, NULL);
6749 * mono_method_body_get_object:
6750 * @domain: an app domain
6753 * Return an System.Reflection.MethodBody object representing the method @method.
6755 MonoReflectionMethodBody*
6756 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6758 static MonoClass *System_Reflection_MethodBody = NULL;
6759 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6760 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6761 MonoReflectionMethodBody *ret;
6762 MonoMethodNormal *mn;
6763 MonoMethodHeader *header;
6764 guint32 method_rva, local_var_sig_token;
6766 unsigned char format, flags;
6769 if (!System_Reflection_MethodBody)
6770 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6771 if (!System_Reflection_LocalVariableInfo)
6772 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6773 if (!System_Reflection_ExceptionHandlingClause)
6774 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6776 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6778 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6779 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6780 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6781 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6783 mn = (MonoMethodNormal *)method;
6784 header = mono_method_get_header (method);
6786 /* Obtain local vars signature token */
6787 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6788 ptr = mono_image_rva_map (method->klass->image, method_rva);
6789 flags = *(const unsigned char *) ptr;
6790 format = flags & METHOD_HEADER_FORMAT_MASK;
6792 case METHOD_HEADER_TINY_FORMAT:
6793 local_var_sig_token = 0;
6795 case METHOD_HEADER_FAT_FORMAT:
6799 local_var_sig_token = read32 (ptr);
6802 g_assert_not_reached ();
6805 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6807 ret->init_locals = header->init_locals;
6808 ret->max_stack = header->max_stack;
6809 ret->local_var_sig_token = local_var_sig_token;
6810 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6811 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6814 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6815 for (i = 0; i < header->num_locals; ++i) {
6816 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6817 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6818 info->is_pinned = header->locals [i]->pinned;
6819 info->local_index = i;
6820 mono_array_setref (ret->locals, i, info);
6824 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6825 for (i = 0; i < header->num_clauses; ++i) {
6826 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6827 MonoExceptionClause *clause = &header->clauses [i];
6829 info->flags = clause->flags;
6830 info->try_offset = clause->try_offset;
6831 info->try_length = clause->try_len;
6832 info->handler_offset = clause->handler_offset;
6833 info->handler_length = clause->handler_len;
6834 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6835 info->filter_offset = clause->data.filter_offset;
6836 else if (clause->data.catch_class)
6837 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6839 mono_array_setref (ret->clauses, i, info);
6842 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6847 * mono_get_dbnull_object:
6848 * @domain: Domain where the object lives
6850 * Returns the System.DBNull.Value singleton object
6852 * Used as the value for ParameterInfo.DefaultValue
6855 mono_get_dbnull_object (MonoDomain *domain)
6858 static MonoClassField *dbnull_value_field = NULL;
6860 if (!dbnull_value_field) {
6861 MonoClass *dbnull_klass;
6862 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6863 mono_class_init (dbnull_klass);
6864 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6865 g_assert (dbnull_value_field);
6867 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6873 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6875 guint32 param_index, i, lastp, crow = 0;
6876 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6879 MonoClass *klass = method->klass;
6880 MonoImage *image = klass->image;
6881 MonoMethodSignature *methodsig = mono_method_signature (method);
6883 MonoTableInfo *constt;
6884 MonoTableInfo *methodt;
6885 MonoTableInfo *paramt;
6887 if (!methodsig->param_count)
6890 mono_class_init (klass);
6892 if (klass->image->dynamic) {
6893 MonoReflectionMethodAux *aux;
6894 if (method->is_inflated)
6895 method = ((MonoMethodInflated*)method)->declaring;
6896 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6897 if (aux && aux->param_defaults) {
6898 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6899 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6904 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6905 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6906 constt = &image->tables [MONO_TABLE_CONSTANT];
6908 idx = mono_method_get_index (method) - 1;
6909 g_assert (idx != -1);
6911 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6912 if (idx + 1 < methodt->rows)
6913 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6915 lastp = paramt->rows + 1;
6917 for (i = param_index; i < lastp; ++i) {
6920 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6921 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6923 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6926 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6931 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6932 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6933 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6940 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6945 MonoType *basetype = type;
6950 klass = mono_class_from_mono_type (type);
6951 if (klass->valuetype) {
6952 object = mono_object_new (domain, klass);
6953 retval = ((gchar *) object + sizeof (MonoObject));
6954 if (klass->enumtype)
6955 basetype = mono_class_enum_basetype (klass);
6960 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6967 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6971 memset (assembly, 0, sizeof (MonoAssemblyName));
6973 assembly->culture = "";
6974 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6976 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6979 while (g_ascii_isspace (*p) || *p == ',') {
6988 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6990 assembly->major = strtoul (p, &s, 10);
6991 if (s == p || *s != '.')
6994 assembly->minor = strtoul (p, &s, 10);
6995 if (s == p || *s != '.')
6998 assembly->build = strtoul (p, &s, 10);
6999 if (s == p || *s != '.')
7002 assembly->revision = strtoul (p, &s, 10);
7006 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7008 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7009 assembly->culture = "";
7012 assembly->culture = p;
7013 while (*p && *p != ',') {
7017 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7019 if (strncmp (p, "null", 4) == 0) {
7024 while (*p && *p != ',') {
7027 len = (p - start + 1);
7028 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7029 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7030 g_strlcpy ((char*)assembly->public_key_token, start, len);
7033 while (*p && *p != ',')
7037 while (g_ascii_isspace (*p) || *p == ',') {
7051 * mono_reflection_parse_type:
7054 * Parse a type name as accepted by the GetType () method and output the info
7055 * extracted in the info structure.
7056 * the name param will be mangled, so, make a copy before passing it to this function.
7057 * The fields in info will be valid until the memory pointed to by name is valid.
7059 * See also mono_type_get_name () below.
7061 * Returns: 0 on parse error.
7064 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7065 MonoTypeNameParse *info)
7067 char *start, *p, *w, *temp, *last_point, *startn;
7068 int in_modifiers = 0;
7069 int isbyref = 0, rank, arity = 0, i;
7071 start = p = w = name;
7073 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7074 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7075 info->name = info->name_space = NULL;
7076 info->nested = NULL;
7077 info->modifiers = NULL;
7078 info->type_arguments = NULL;
7080 /* last_point separates the namespace from the name */
7083 while (*p == ' ') p++, start++, w++, name++;
7088 *p = 0; /* NULL terminate the name */
7090 info->nested = g_list_append (info->nested, startn);
7091 /* we have parsed the nesting namespace + name */
7095 info->name_space = start;
7097 info->name = last_point + 1;
7099 info->name_space = (char *)"";
7118 i = strtol (p, &temp, 10);
7135 info->name_space = start;
7137 info->name = last_point + 1;
7139 info->name_space = (char *)"";
7146 if (isbyref) /* only one level allowed by the spec */
7149 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7153 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7159 info->type_arguments = g_ptr_array_new ();
7160 for (i = 0; i < arity; i++) {
7161 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7162 gboolean fqname = FALSE;
7164 g_ptr_array_add (info->type_arguments, subinfo);
7171 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7182 while (*p && (*p != ']'))
7190 if (g_ascii_isspace (*aname)) {
7197 !assembly_name_to_aname (&subinfo->assembly, aname))
7201 if (i + 1 < arity) {
7221 else if (*p == '*') /* '*' means unknown lower bound */
7222 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7229 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7240 if (g_ascii_isspace (*p)) {
7247 return 0; /* missing assembly name */
7248 if (!assembly_name_to_aname (&info->assembly, p))
7254 if (info->assembly.name)
7257 // *w = 0; /* terminate class name */
7259 if (!info->name || !*info->name)
7263 /* add other consistency checks */
7268 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7270 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7274 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7276 gboolean type_resolve = FALSE;
7278 MonoImage *rootimage = image;
7280 if (info->assembly.name) {
7281 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7282 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7284 * This could happen in the AOT compiler case when the search hook is not
7287 assembly = image->assembly;
7289 /* then we must load the assembly ourselve - see #60439 */
7290 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7294 image = assembly->image;
7295 } else if (!image) {
7296 image = mono_defaults.corlib;
7299 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7300 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7301 image = mono_defaults.corlib;
7302 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7309 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7314 gboolean bounded = FALSE;
7317 image = mono_defaults.corlib;
7320 klass = mono_class_from_name_case (image, info->name_space, info->name);
7322 klass = mono_class_from_name (image, info->name_space, info->name);
7325 for (mod = info->nested; mod; mod = mod->next) {
7326 gpointer iter = NULL;
7330 mono_class_init (parent);
7332 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7334 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7337 if (strcmp (klass->name, mod->data) == 0)
7346 mono_class_init (klass);
7348 if (info->type_arguments) {
7349 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7350 MonoReflectionType *the_type;
7354 for (i = 0; i < info->type_arguments->len; i++) {
7355 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7357 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7358 if (!type_args [i]) {
7364 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7366 instance = mono_reflection_bind_generic_parameters (
7367 the_type, info->type_arguments->len, type_args);
7373 klass = mono_class_from_mono_type (instance);
7376 for (mod = info->modifiers; mod; mod = mod->next) {
7377 modval = GPOINTER_TO_UINT (mod->data);
7378 if (!modval) { /* byref: must be last modifier */
7379 return &klass->this_arg;
7380 } else if (modval == -1) {
7381 klass = mono_ptr_class_get (&klass->byval_arg);
7382 } else if (modval == -2) {
7384 } else { /* array rank */
7385 klass = mono_bounded_array_class_get (klass, modval, bounded);
7387 mono_class_init (klass);
7390 return &klass->byval_arg;
7394 * mono_reflection_get_type:
7395 * @image: a metadata context
7396 * @info: type description structure
7397 * @ignorecase: flag for case-insensitive string compares
7398 * @type_resolve: whenever type resolve was already tried
7400 * Build a MonoType from the type description in @info.
7405 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7406 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7410 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7412 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7416 g_assert (assembly->dynamic);
7418 /* Enumerate all modules */
7421 if (abuilder->modules) {
7422 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7423 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7424 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7430 if (!type && abuilder->loaded_modules) {
7431 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7432 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7433 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7443 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7446 MonoReflectionAssembly *assembly;
7450 if (image && image->dynamic)
7451 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7453 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7456 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7463 *type_resolve = TRUE;
7466 /* Reconstruct the type name */
7467 fullName = g_string_new ("");
7468 if (info->name_space && (info->name_space [0] != '\0'))
7469 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7471 g_string_printf (fullName, "%s", info->name);
7472 for (mod = info->nested; mod; mod = mod->next)
7473 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7475 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7477 if (assembly->assembly->dynamic)
7478 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7480 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7483 g_string_free (fullName, TRUE);
7488 mono_reflection_free_type_info (MonoTypeNameParse *info)
7490 g_list_free (info->modifiers);
7491 g_list_free (info->nested);
7493 if (info->type_arguments) {
7496 for (i = 0; i < info->type_arguments->len; i++) {
7497 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7499 mono_reflection_free_type_info (subinfo);
7500 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7504 g_ptr_array_free (info->type_arguments, TRUE);
7509 * mono_reflection_type_from_name:
7511 * @image: a metadata context (can be NULL).
7513 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7514 * it defaults to get the type from @image or, if @image is NULL or loading
7515 * from it fails, uses corlib.
7519 mono_reflection_type_from_name (char *name, MonoImage *image)
7521 MonoType *type = NULL;
7522 MonoTypeNameParse info;
7525 /* Make a copy since parse_type modifies its argument */
7526 tmp = g_strdup (name);
7528 /*g_print ("requested type %s\n", str);*/
7529 if (mono_reflection_parse_type (tmp, &info)) {
7530 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7534 mono_reflection_free_type_info (&info);
7539 * mono_reflection_get_token:
7541 * Return the metadata token of OBJ which should be an object
7542 * representing a metadata element.
7545 mono_reflection_get_token (MonoObject *obj)
7550 klass = obj->vtable->klass;
7552 if (strcmp (klass->name, "MethodBuilder") == 0) {
7553 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7555 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7556 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7557 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7559 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7560 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7561 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7563 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7564 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7565 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7566 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7567 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7568 } else if (strcmp (klass->name, "MonoType") == 0) {
7569 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7570 token = mono_class_from_mono_type (type)->type_token;
7571 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7572 strcmp (klass->name, "MonoMethod") == 0 ||
7573 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7574 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7575 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7576 if (m->method->is_inflated) {
7577 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7578 return inflated->declaring->token;
7580 token = m->method->token;
7582 } else if (strcmp (klass->name, "MonoField") == 0) {
7583 MonoReflectionField *f = (MonoReflectionField*)obj;
7585 if (is_field_on_inst (f->field)) {
7586 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7587 int field_index = f->field - dgclass->fields;
7590 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7591 obj = dgclass->field_objects [field_index];
7592 return mono_reflection_get_token (obj);
7594 token = mono_class_get_field_token (f->field);
7595 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7596 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7598 token = mono_class_get_property_token (p->property);
7599 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7600 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7602 token = mono_class_get_event_token (p->event);
7603 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7604 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7606 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7607 } else if (strcmp (klass->name, "Module") == 0) {
7608 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7611 } else if (strcmp (klass->name, "Assembly") == 0) {
7612 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7614 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7615 MonoException *ex = mono_get_exception_not_implemented (msg);
7617 mono_raise_exception (ex);
7624 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7626 int slen, type = t->type;
7627 MonoClass *tklass = t->data.klass;
7633 case MONO_TYPE_BOOLEAN: {
7634 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7639 case MONO_TYPE_CHAR:
7641 case MONO_TYPE_I2: {
7642 guint16 *val = g_malloc (sizeof (guint16));
7647 #if SIZEOF_VOID_P == 4
7653 case MONO_TYPE_I4: {
7654 guint32 *val = g_malloc (sizeof (guint32));
7659 #if SIZEOF_VOID_P == 8
7660 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7664 case MONO_TYPE_I8: {
7665 guint64 *val = g_malloc (sizeof (guint64));
7670 case MONO_TYPE_R8: {
7671 double *val = g_malloc (sizeof (double));
7676 case MONO_TYPE_VALUETYPE:
7677 if (t->data.klass->enumtype) {
7678 type = mono_class_enum_basetype (t->data.klass)->type;
7681 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7684 case MONO_TYPE_STRING:
7685 if (*p == (char)0xFF) {
7689 slen = mono_metadata_decode_value (p, &p);
7691 return mono_string_new_len (mono_domain_get (), p, slen);
7692 case MONO_TYPE_CLASS: {
7695 if (*p == (char)0xFF) {
7700 slen = mono_metadata_decode_value (p, &p);
7701 n = g_memdup (p, slen + 1);
7703 t = mono_reflection_type_from_name (n, image);
7705 g_warning ("Cannot load type '%s'", n);
7709 return mono_type_get_object (mono_domain_get (), t);
7713 case MONO_TYPE_OBJECT: {
7716 MonoClass *subc = NULL;
7721 } else if (subt == 0x0E) {
7722 type = MONO_TYPE_STRING;
7724 } else if (subt == 0x1D) {
7725 MonoType simple_type = {{0}};
7730 /* See Partition II, Appendix B3 */
7731 etype = MONO_TYPE_OBJECT;
7732 type = MONO_TYPE_SZARRAY;
7733 simple_type.type = etype;
7734 tklass = mono_class_from_mono_type (&simple_type);
7736 } else if (subt == 0x55) {
7739 slen = mono_metadata_decode_value (p, &p);
7740 n = g_memdup (p, slen + 1);
7742 t = mono_reflection_type_from_name (n, image);
7744 g_error ("Cannot load type '%s'", n);
7747 subc = mono_class_from_mono_type (t);
7748 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7749 MonoType simple_type = {{0}};
7750 simple_type.type = subt;
7751 subc = mono_class_from_mono_type (&simple_type);
7753 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7755 val = load_cattr_value (image, &subc->byval_arg, p, end);
7756 obj = mono_object_new (mono_domain_get (), subc);
7757 g_assert (!subc->has_references);
7758 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7762 case MONO_TYPE_SZARRAY: {
7764 guint32 i, alen, basetype;
7767 if (alen == 0xffffffff) {
7771 arr = mono_array_new (mono_domain_get(), tklass, alen);
7772 basetype = tklass->byval_arg.type;
7773 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7774 basetype = mono_class_enum_basetype (tklass)->type;
7779 case MONO_TYPE_BOOLEAN:
7780 for (i = 0; i < alen; i++) {
7781 MonoBoolean val = *p++;
7782 mono_array_set (arr, MonoBoolean, i, val);
7785 case MONO_TYPE_CHAR:
7788 for (i = 0; i < alen; i++) {
7789 guint16 val = read16 (p);
7790 mono_array_set (arr, guint16, i, val);
7797 for (i = 0; i < alen; i++) {
7798 guint32 val = read32 (p);
7799 mono_array_set (arr, guint32, i, val);
7804 for (i = 0; i < alen; i++) {
7807 mono_array_set (arr, double, i, val);
7813 for (i = 0; i < alen; i++) {
7814 guint64 val = read64 (p);
7815 mono_array_set (arr, guint64, i, val);
7819 case MONO_TYPE_CLASS:
7820 case MONO_TYPE_OBJECT:
7821 case MONO_TYPE_STRING:
7822 for (i = 0; i < alen; i++) {
7823 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7824 mono_array_setref (arr, i, item);
7828 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7834 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7840 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7842 static MonoClass *klass;
7843 static MonoMethod *ctor;
7845 void *params [2], *unboxed;
7848 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7850 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7852 params [0] = mono_type_get_object (mono_domain_get (), t);
7854 retval = mono_object_new (mono_domain_get (), klass);
7855 unboxed = mono_object_unbox (retval);
7856 mono_runtime_invoke (ctor, unboxed, params, NULL);
7862 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7864 static MonoClass *klass;
7865 static MonoMethod *ctor;
7867 void *unboxed, *params [2];
7870 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7872 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7875 params [1] = typedarg;
7876 retval = mono_object_new (mono_domain_get (), klass);
7877 unboxed = mono_object_unbox (retval);
7878 mono_runtime_invoke (ctor, unboxed, params, NULL);
7884 type_is_reference (MonoType *type)
7886 switch (type->type) {
7887 case MONO_TYPE_BOOLEAN:
7888 case MONO_TYPE_CHAR:
7901 case MONO_TYPE_VALUETYPE:
7909 free_param_data (MonoMethodSignature *sig, void **params) {
7911 for (i = 0; i < sig->param_count; ++i) {
7912 if (!type_is_reference (sig->params [i]))
7913 g_free (params [i]);
7918 * Find the field index in the metadata FieldDef table.
7921 find_field_index (MonoClass *klass, MonoClassField *field) {
7924 for (i = 0; i < klass->field.count; ++i) {
7925 if (field == &klass->fields [i])
7926 return klass->field.first + 1 + i;
7932 * Find the property index in the metadata Property table.
7935 find_property_index (MonoClass *klass, MonoProperty *property) {
7938 for (i = 0; i < klass->ext->property.count; ++i) {
7939 if (property == &klass->ext->properties [i])
7940 return klass->ext->property.first + 1 + i;
7946 * Find the event index in the metadata Event table.
7949 find_event_index (MonoClass *klass, MonoEvent *event) {
7952 for (i = 0; i < klass->ext->event.count; ++i) {
7953 if (event == &klass->ext->events [i])
7954 return klass->ext->event.first + 1 + i;
7960 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7962 const char *p = (const char*)data;
7964 guint32 i, j, num_named;
7966 void *params_buf [32];
7968 MonoMethodSignature *sig;
7970 mono_class_init (method->klass);
7973 attr = mono_object_new (mono_domain_get (), method->klass);
7974 mono_runtime_invoke (method, attr, NULL, NULL);
7978 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7981 /*g_print ("got attr %s\n", method->klass->name);*/
7983 sig = mono_method_signature (method);
7984 if (sig->param_count < 32)
7985 params = params_buf;
7987 /* Allocate using GC so it gets GC tracking */
7988 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7992 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7993 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7997 attr = mono_object_new (mono_domain_get (), method->klass);
7998 mono_runtime_invoke (method, attr, params, NULL);
7999 free_param_data (method->signature, params);
8000 num_named = read16 (named);
8002 for (j = 0; j < num_named; j++) {
8004 char *name, named_type, data_type;
8005 named_type = *named++;
8006 data_type = *named++; /* type of data */
8007 if (data_type == MONO_TYPE_SZARRAY)
8008 data_type = *named++;
8009 if (data_type == MONO_TYPE_ENUM) {
8012 type_len = mono_metadata_decode_blob_size (named, &named);
8013 type_name = g_malloc (type_len + 1);
8014 memcpy (type_name, named, type_len);
8015 type_name [type_len] = 0;
8017 /* FIXME: lookup the type and check type consistency */
8020 name_len = mono_metadata_decode_blob_size (named, &named);
8021 name = g_malloc (name_len + 1);
8022 memcpy (name, named, name_len);
8023 name [name_len] = 0;
8025 if (named_type == 0x53) {
8026 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8027 void *val = load_cattr_value (image, field->type, named, &named);
8028 mono_field_set_value (attr, field, val);
8029 if (!type_is_reference (field->type))
8031 } else if (named_type == 0x54) {
8034 MonoType *prop_type;
8036 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8037 /* can we have more that 1 arg in a custom attr named property? */
8038 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8039 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8040 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8041 mono_property_set_value (prop, attr, pparams, NULL);
8042 if (!type_is_reference (prop_type))
8043 g_free (pparams [0]);
8048 if (params != params_buf)
8049 mono_gc_free_fixed (params);
8055 * mono_reflection_create_custom_attr_data_args:
8057 * Create an array of typed and named arguments from the cattr blob given by DATA.
8058 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8059 * NAMED_ARG_INFO will contain information about the named arguments.
8062 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)
8064 MonoArray *typedargs, *namedargs;
8065 MonoClass *attrklass;
8067 const char *p = (const char*)data;
8069 guint32 i, j, num_named;
8070 CattrNamedArg *arginfo = NULL;
8072 mono_class_init (method->klass);
8076 *named_arg_info = NULL;
8078 domain = mono_domain_get ();
8080 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8083 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8087 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8091 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8092 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8093 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8094 mono_array_setref (typedargs, i, obj);
8096 if (!type_is_reference (mono_method_signature (method)->params [i]))
8101 num_named = read16 (named);
8102 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8104 attrklass = method->klass;
8106 arginfo = g_new0 (CattrNamedArg, num_named);
8107 *named_arg_info = arginfo;
8109 for (j = 0; j < num_named; j++) {
8111 char *name, named_type, data_type;
8112 named_type = *named++;
8113 data_type = *named++; /* type of data */
8114 if (data_type == MONO_TYPE_SZARRAY)
8115 data_type = *named++;
8116 if (data_type == MONO_TYPE_ENUM) {
8119 type_len = mono_metadata_decode_blob_size (named, &named);
8120 type_name = g_malloc (type_len + 1);
8121 memcpy (type_name, named, type_len);
8122 type_name [type_len] = 0;
8124 /* FIXME: lookup the type and check type consistency */
8127 name_len = mono_metadata_decode_blob_size (named, &named);
8128 name = g_malloc (name_len + 1);
8129 memcpy (name, named, name_len);
8130 name [name_len] = 0;
8132 if (named_type == 0x53) {
8134 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8137 arginfo [j].type = field->type;
8138 arginfo [j].field = field;
8140 val = load_cattr_value (image, field->type, named, &named);
8141 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8142 mono_array_setref (namedargs, j, obj);
8143 if (!type_is_reference (field->type))
8145 } else if (named_type == 0x54) {
8147 MonoType *prop_type;
8148 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8151 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8152 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8154 arginfo [j].type = prop_type;
8155 arginfo [j].prop = prop;
8157 val = load_cattr_value (image, prop_type, named, &named);
8158 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8159 mono_array_setref (namedargs, j, obj);
8160 if (!type_is_reference (prop_type))
8166 *typed_args = typedargs;
8167 *named_args = namedargs;
8171 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8173 MonoArray *typedargs, *namedargs;
8174 static MonoMethod *ctor;
8178 CattrNamedArg *arginfo;
8181 mono_class_init (method->klass);
8184 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8186 domain = mono_domain_get ();
8188 /* This is for Attributes with no parameters */
8189 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8190 params [0] = mono_method_get_object (domain, method, NULL);
8191 params [1] = params [2] = NULL;
8192 mono_runtime_invoke (method, attr, params, NULL);
8196 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8197 if (!typedargs || !namedargs)
8200 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8201 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8202 MonoObject *typedarg;
8204 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8205 mono_array_setref (typedargs, i, typedarg);
8208 for (i = 0; i < mono_array_length (namedargs); ++i) {
8209 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8210 MonoObject *typedarg, *namedarg, *minfo;
8212 if (arginfo [i].prop)
8213 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8215 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8217 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8218 namedarg = create_cattr_named_arg (minfo, typedarg);
8220 mono_array_setref (namedargs, i, namedarg);
8223 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8224 params [0] = mono_method_get_object (domain, method, NULL);
8225 params [1] = typedargs;
8226 params [2] = namedargs;
8227 mono_runtime_invoke (ctor, attr, params, NULL);
8232 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8238 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8239 for (i = 0; i < cinfo->num_attrs; ++i) {
8240 if (!cinfo->attrs [i].ctor)
8241 /* The cattr type is not finished yet */
8242 /* We should include the type name but cinfo doesn't contain it */
8243 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8244 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8245 mono_array_setref (result, i, attr);
8251 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8258 for (i = 0; i < cinfo->num_attrs; ++i) {
8259 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8263 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8265 for (i = 0; i < cinfo->num_attrs; ++i) {
8266 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8267 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8268 mono_array_setref (result, n, attr);
8276 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8282 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8283 for (i = 0; i < cinfo->num_attrs; ++i) {
8284 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8285 mono_array_setref (result, i, attr);
8291 * mono_custom_attrs_from_index:
8293 * Returns: NULL if no attributes are found or if a loading error occurs.
8296 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8298 guint32 mtoken, i, len;
8299 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8301 MonoCustomAttrInfo *ainfo;
8302 GList *tmp, *list = NULL;
8305 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8307 i = mono_metadata_custom_attrs_from_index (image, idx);
8311 while (i < ca->rows) {
8312 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8314 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8317 len = g_list_length (list);
8320 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8321 ainfo->num_attrs = len;
8322 ainfo->image = image;
8323 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8324 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8325 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8326 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8327 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8328 mtoken |= MONO_TOKEN_METHOD_DEF;
8330 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8331 mtoken |= MONO_TOKEN_MEMBER_REF;
8334 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8337 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8338 if (!ainfo->attrs [i].ctor) {
8339 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8344 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8345 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8346 ainfo->attrs [i].data = (guchar*)data;
8354 mono_custom_attrs_from_method (MonoMethod *method)
8359 * An instantiated method has the same cattrs as the generic method definition.
8361 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8362 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8364 if (method->is_inflated)
8365 method = ((MonoMethodInflated *) method)->declaring;
8367 if (method->dynamic || method->klass->image->dynamic)
8368 return lookup_custom_attr (method->klass->image, method);
8371 /* Synthetic methods */
8374 idx = mono_method_get_index (method);
8375 idx <<= MONO_CUSTOM_ATTR_BITS;
8376 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8377 return mono_custom_attrs_from_index (method->klass->image, idx);
8381 mono_custom_attrs_from_class (MonoClass *klass)
8385 if (klass->generic_class)
8386 klass = klass->generic_class->container_class;
8388 if (klass->image->dynamic)
8389 return lookup_custom_attr (klass->image, klass);
8391 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8392 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8393 idx <<= MONO_CUSTOM_ATTR_BITS;
8394 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8396 idx = mono_metadata_token_index (klass->type_token);
8397 idx <<= MONO_CUSTOM_ATTR_BITS;
8398 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8400 return mono_custom_attrs_from_index (klass->image, idx);
8404 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8408 if (assembly->image->dynamic)
8409 return lookup_custom_attr (assembly->image, assembly);
8410 idx = 1; /* there is only one assembly */
8411 idx <<= MONO_CUSTOM_ATTR_BITS;
8412 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8413 return mono_custom_attrs_from_index (assembly->image, idx);
8416 static MonoCustomAttrInfo*
8417 mono_custom_attrs_from_module (MonoImage *image)
8422 return lookup_custom_attr (image, image);
8423 idx = 1; /* there is only one module */
8424 idx <<= MONO_CUSTOM_ATTR_BITS;
8425 idx |= MONO_CUSTOM_ATTR_MODULE;
8426 return mono_custom_attrs_from_index (image, idx);
8430 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8434 if (klass->image->dynamic) {
8435 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8436 return lookup_custom_attr (klass->image, property);
8438 idx = find_property_index (klass, property);
8439 idx <<= MONO_CUSTOM_ATTR_BITS;
8440 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8441 return mono_custom_attrs_from_index (klass->image, idx);
8445 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8449 if (klass->image->dynamic) {
8450 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8451 return lookup_custom_attr (klass->image, event);
8453 idx = find_event_index (klass, event);
8454 idx <<= MONO_CUSTOM_ATTR_BITS;
8455 idx |= MONO_CUSTOM_ATTR_EVENT;
8456 return mono_custom_attrs_from_index (klass->image, idx);
8460 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8463 if (klass->image->dynamic) {
8464 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8465 return lookup_custom_attr (klass->image, field);
8467 idx = find_field_index (klass, field);
8468 idx <<= MONO_CUSTOM_ATTR_BITS;
8469 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8470 return mono_custom_attrs_from_index (klass->image, idx);
8474 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8477 guint32 i, idx, method_index;
8478 guint32 param_list, param_last, param_pos, found;
8480 MonoReflectionMethodAux *aux;
8483 * An instantiated method has the same cattrs as the generic method definition.
8485 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8486 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8488 if (method->is_inflated)
8489 method = ((MonoMethodInflated *) method)->declaring;
8491 if (method->klass->image->dynamic) {
8492 MonoCustomAttrInfo *res, *ainfo;
8495 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8496 if (!aux || !aux->param_cattr)
8499 /* Need to copy since it will be freed later */
8500 ainfo = aux->param_cattr [param];
8501 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8502 res = g_malloc0 (size);
8503 memcpy (res, ainfo, size);
8507 image = method->klass->image;
8508 method_index = mono_method_get_index (method);
8509 ca = &image->tables [MONO_TABLE_METHOD];
8511 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8512 if (method_index == ca->rows) {
8513 ca = &image->tables [MONO_TABLE_PARAM];
8514 param_last = ca->rows + 1;
8516 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8517 ca = &image->tables [MONO_TABLE_PARAM];
8520 for (i = param_list; i < param_last; ++i) {
8521 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8522 if (param_pos == param) {
8530 idx <<= MONO_CUSTOM_ATTR_BITS;
8531 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8532 return mono_custom_attrs_from_index (image, idx);
8536 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8540 for (i = 0; i < ainfo->num_attrs; ++i) {
8541 klass = ainfo->attrs [i].ctor->klass;
8542 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8549 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8556 for (i = 0; i < ainfo->num_attrs; ++i) {
8557 klass = ainfo->attrs [i].ctor->klass;
8558 if (mono_class_has_parent (klass, attr_klass)) {
8563 if (attr_index == -1)
8566 attrs = mono_custom_attrs_construct (ainfo);
8568 return mono_array_get (attrs, MonoObject*, attr_index);
8574 * mono_reflection_get_custom_attrs_info:
8575 * @obj: a reflection object handle
8577 * Return the custom attribute info for attributes defined for the
8578 * reflection handle @obj. The objects.
8580 * FIXME this function leaks like a sieve for SRE objects.
8583 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8586 MonoCustomAttrInfo *cinfo = NULL;
8588 klass = obj->vtable->klass;
8589 if (klass == mono_defaults.monotype_class) {
8590 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8591 klass = mono_class_from_mono_type (type);
8592 cinfo = mono_custom_attrs_from_class (klass);
8593 } else if (strcmp ("Assembly", klass->name) == 0) {
8594 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8595 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8596 } else if (strcmp ("Module", klass->name) == 0) {
8597 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8598 cinfo = mono_custom_attrs_from_module (module->image);
8599 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8600 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8601 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8602 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8603 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8604 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8605 } else if (strcmp ("MonoField", klass->name) == 0) {
8606 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8607 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8608 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8609 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8610 cinfo = mono_custom_attrs_from_method (rmethod->method);
8611 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8612 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8613 cinfo = mono_custom_attrs_from_method (rmethod->method);
8614 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8615 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8616 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8617 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8618 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8619 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8620 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8621 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8622 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8623 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8624 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8625 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8626 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8627 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8628 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8629 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8630 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8631 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8632 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8633 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8634 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8635 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8636 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8637 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8638 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8639 } else { /* handle other types here... */
8640 g_error ("get custom attrs not yet supported for %s", klass->name);
8647 * mono_reflection_get_custom_attrs_by_type:
8648 * @obj: a reflection object handle
8650 * Return an array with all the custom attributes defined of the
8651 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8652 * of that type are returned. The objects are fully build. Return NULL if a loading error
8656 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8659 MonoCustomAttrInfo *cinfo;
8661 cinfo = mono_reflection_get_custom_attrs_info (obj);
8664 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8666 result = mono_custom_attrs_construct (cinfo);
8668 mono_custom_attrs_free (cinfo);
8670 if (mono_loader_get_last_error ())
8672 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8679 * mono_reflection_get_custom_attrs:
8680 * @obj: a reflection object handle
8682 * Return an array with all the custom attributes defined of the
8683 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8687 mono_reflection_get_custom_attrs (MonoObject *obj)
8689 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8693 * mono_reflection_get_custom_attrs_data:
8694 * @obj: a reflection obj handle
8696 * Returns an array of System.Reflection.CustomAttributeData,
8697 * which include information about attributes reflected on
8698 * types loaded using the Reflection Only methods
8701 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8704 MonoCustomAttrInfo *cinfo;
8706 cinfo = mono_reflection_get_custom_attrs_info (obj);
8708 result = mono_custom_attrs_data_construct (cinfo);
8710 mono_custom_attrs_free (cinfo);
8712 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8717 static MonoReflectionType*
8718 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8720 static MonoMethod *method_get_underlying_system_type = NULL;
8721 MonoMethod *usertype_method;
8723 if (!method_get_underlying_system_type)
8724 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8725 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8726 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8729 #ifndef DISABLE_REFLECTION_EMIT
8732 is_corlib_type (MonoClass *class)
8734 return class->image == mono_defaults.corlib;
8737 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8738 static MonoClass *cached_class; \
8740 return cached_class == _class; \
8741 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8742 cached_class = _class; \
8749 is_sre_array (MonoClass *class)
8751 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8755 is_sre_byref (MonoClass *class)
8757 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8761 is_sre_pointer (MonoClass *class)
8763 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8767 is_sre_generic_instance (MonoClass *class)
8769 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8773 is_sre_type_builder (MonoClass *class)
8775 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8779 is_sre_method_builder (MonoClass *class)
8781 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8785 is_sre_ctor_builder (MonoClass *class)
8787 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8791 is_sre_field_builder (MonoClass *class)
8793 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8797 is_sr_mono_method (MonoClass *class)
8799 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
8803 is_sr_mono_cmethod (MonoClass *class)
8805 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
8809 is_sr_mono_field (MonoClass *class)
8811 check_corlib_type_cached (class, "System.Reflection", "MonoField");
8816 mono_reflection_type_get_handle (MonoReflectionType* ref)
8824 if (is_usertype (ref)) {
8825 ref = mono_reflection_type_get_underlying_system_type (ref);
8826 g_assert (!is_usertype (ref)); /*FIXME fail better*/
8831 class = mono_object_class (ref);
8833 if (is_sre_array (class)) {
8835 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8836 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8838 if (sre_array->rank == 0) //single dimentional array
8839 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8841 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8842 sre_array->type.type = res;
8844 } else if (is_sre_byref (class)) {
8846 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8847 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8849 res = &mono_class_from_mono_type (base)->this_arg;
8850 sre_byref->type.type = res;
8852 } else if (is_sre_pointer (class)) {
8854 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8855 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8857 res = &mono_ptr_class_get (base)->byval_arg;
8858 sre_pointer->type.type = res;
8860 } else if (is_sre_generic_instance (class)) {
8861 MonoType *res, **types;
8862 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8865 count = mono_array_length (gclass->type_arguments);
8866 types = g_new0 (MonoType*, count);
8867 for (i = 0; i < count; ++i) {
8868 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8869 types [i] = mono_reflection_type_get_handle (t);
8872 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
8875 gclass->type.type = res;
8879 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8886 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8888 mono_reflection_type_get_handle (type);
8892 mono_reflection_register_with_runtime (MonoReflectionType *type)
8894 MonoType *res = mono_reflection_type_get_handle (type);
8895 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
8896 MonoClass *class = mono_class_from_mono_type (res);
8899 mono_loader_lock (); /*same locking as mono_type_get_object*/
8900 mono_domain_lock (domain);
8902 if (!class->image->dynamic)
8903 mono_class_setup_supertypes (class);
8905 if (!domain->type_hash)
8906 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
8907 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
8908 mono_g_hash_table_insert (domain->type_hash, res, type);
8910 mono_domain_unlock (domain);
8911 mono_loader_unlock ();
8915 * LOCKING: Assumes the loader lock is held.
8917 static MonoMethodSignature*
8918 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8919 MonoMethodSignature *sig;
8922 count = parameters? mono_array_length (parameters): 0;
8924 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8925 sig->param_count = count;
8926 sig->sentinelpos = -1; /* FIXME */
8927 for (i = 0; i < count; ++i)
8928 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8933 * LOCKING: Assumes the loader lock is held.
8935 static MonoMethodSignature*
8936 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8937 MonoMethodSignature *sig;
8939 sig = parameters_to_signature (image, ctor->parameters);
8940 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8941 sig->ret = &mono_defaults.void_class->byval_arg;
8946 * LOCKING: Assumes the loader lock is held.
8948 static MonoMethodSignature*
8949 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8950 MonoMethodSignature *sig;
8952 sig = parameters_to_signature (image, method->parameters);
8953 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8954 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8955 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8959 static MonoMethodSignature*
8960 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8961 MonoMethodSignature *sig;
8963 sig = parameters_to_signature (NULL, method->parameters);
8964 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8965 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8966 sig->generic_param_count = 0;
8971 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8973 MonoClass *klass = mono_object_class (prop);
8974 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8975 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8976 *name = mono_string_to_utf8 (pb->name);
8977 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
8979 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8980 *name = g_strdup (p->property->name);
8981 if (p->property->get)
8982 *type = mono_method_signature (p->property->get)->ret;
8984 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8989 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8991 MonoClass *klass = mono_object_class (field);
8992 if (strcmp (klass->name, "FieldBuilder") == 0) {
8993 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8994 *name = mono_string_to_utf8 (fb->name);
8995 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
8997 MonoReflectionField *f = (MonoReflectionField *)field;
8998 *name = g_strdup (mono_field_get_name (f->field));
8999 *type = f->field->type;
9002 #endif /* !DISABLE_REFLECTION_EMIT */
9005 is_usertype (MonoReflectionType *ref)
9007 MonoClass *class = mono_object_class (ref);
9008 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9011 static MonoReflectionType*
9012 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9014 if (!type || type->type)
9017 if (is_usertype (type)) {
9018 type = mono_reflection_type_get_underlying_system_type (type);
9019 if (is_usertype (type))
9020 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9026 * Encode a value in a custom attribute stream of bytes.
9027 * The value to encode is either supplied as an object in argument val
9028 * (valuetypes are boxed), or as a pointer to the data in the
9030 * @type represents the type of the value
9031 * @buffer is the start of the buffer
9032 * @p the current position in the buffer
9033 * @buflen contains the size of the buffer and is used to return the new buffer size
9034 * if this needs to be realloced.
9035 * @retbuffer and @retp return the start and the position of the buffer
9038 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9040 MonoTypeEnum simple_type;
9042 if ((p-buffer) + 10 >= *buflen) {
9045 newbuf = g_realloc (buffer, *buflen);
9046 p = newbuf + (p-buffer);
9050 argval = ((char*)arg + sizeof (MonoObject));
9051 simple_type = type->type;
9053 switch (simple_type) {
9054 case MONO_TYPE_BOOLEAN:
9059 case MONO_TYPE_CHAR:
9062 swap_with_size (p, argval, 2, 1);
9068 swap_with_size (p, argval, 4, 1);
9072 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9082 swap_with_size (p, argval, 8, 1);
9088 swap_with_size (p, argval, 8, 1);
9091 case MONO_TYPE_VALUETYPE:
9092 if (type->data.klass->enumtype) {
9093 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9096 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9099 case MONO_TYPE_STRING: {
9106 str = mono_string_to_utf8 ((MonoString*)arg);
9107 slen = strlen (str);
9108 if ((p-buffer) + 10 + slen >= *buflen) {
9112 newbuf = g_realloc (buffer, *buflen);
9113 p = newbuf + (p-buffer);
9116 mono_metadata_encode_value (slen, p, &p);
9117 memcpy (p, str, slen);
9122 case MONO_TYPE_CLASS: {
9130 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9131 slen = strlen (str);
9132 if ((p-buffer) + 10 + slen >= *buflen) {
9136 newbuf = g_realloc (buffer, *buflen);
9137 p = newbuf + (p-buffer);
9140 mono_metadata_encode_value (slen, p, &p);
9141 memcpy (p, str, slen);
9146 case MONO_TYPE_SZARRAY: {
9148 MonoClass *eclass, *arg_eclass;
9151 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9154 len = mono_array_length ((MonoArray*)arg);
9156 *p++ = (len >> 8) & 0xff;
9157 *p++ = (len >> 16) & 0xff;
9158 *p++ = (len >> 24) & 0xff;
9160 *retbuffer = buffer;
9161 eclass = type->data.klass;
9162 arg_eclass = mono_object_class (arg)->element_class;
9165 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9166 eclass = mono_defaults.object_class;
9168 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9169 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9170 int elsize = mono_class_array_element_size (arg_eclass);
9171 for (i = 0; i < len; ++i) {
9172 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9175 } else if (eclass->valuetype && arg_eclass->valuetype) {
9176 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9177 int elsize = mono_class_array_element_size (eclass);
9178 for (i = 0; i < len; ++i) {
9179 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9183 for (i = 0; i < len; ++i) {
9184 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9189 case MONO_TYPE_OBJECT: {
9195 * The parameter type is 'object' but the type of the actual
9196 * argument is not. So we have to add type information to the blob
9197 * too. This is completely undocumented in the spec.
9201 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9206 klass = mono_object_class (arg);
9208 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9211 } else if (klass->enumtype) {
9213 } else if (klass == mono_defaults.string_class) {
9214 simple_type = MONO_TYPE_STRING;
9217 } else if (klass->rank == 1) {
9219 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9220 /* See Partition II, Appendix B3 */
9223 *p++ = klass->element_class->byval_arg.type;
9224 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9226 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9227 *p++ = simple_type = klass->byval_arg.type;
9230 g_error ("unhandled type in custom attr");
9232 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9233 slen = strlen (str);
9234 if ((p-buffer) + 10 + slen >= *buflen) {
9238 newbuf = g_realloc (buffer, *buflen);
9239 p = newbuf + (p-buffer);
9242 mono_metadata_encode_value (slen, p, &p);
9243 memcpy (p, str, slen);
9246 simple_type = mono_class_enum_basetype (klass)->type;
9250 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9253 *retbuffer = buffer;
9257 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9259 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9260 char *str = type_get_qualified_name (type, NULL);
9261 int slen = strlen (str);
9265 * This seems to be optional...
9268 mono_metadata_encode_value (slen, p, &p);
9269 memcpy (p, str, slen);
9272 } else if (type->type == MONO_TYPE_OBJECT) {
9274 } else if (type->type == MONO_TYPE_CLASS) {
9275 /* it should be a type: encode_cattr_value () has the check */
9278 mono_metadata_encode_value (type->type, p, &p);
9279 if (type->type == MONO_TYPE_SZARRAY)
9280 /* See the examples in Partition VI, Annex B */
9281 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9287 #ifndef DISABLE_REFLECTION_EMIT
9289 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9292 /* Preallocate a large enough buffer */
9293 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9294 char *str = type_get_qualified_name (type, NULL);
9297 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9298 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9304 len += strlen (name);
9306 if ((p-buffer) + 20 + len >= *buflen) {
9310 newbuf = g_realloc (buffer, *buflen);
9311 p = newbuf + (p-buffer);
9315 encode_field_or_prop_type (type, p, &p);
9317 len = strlen (name);
9318 mono_metadata_encode_value (len, p, &p);
9319 memcpy (p, name, len);
9321 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9323 *retbuffer = buffer;
9327 * mono_reflection_get_custom_attrs_blob:
9328 * @ctor: custom attribute constructor
9329 * @ctorArgs: arguments o the constructor
9335 * Creates the blob of data that needs to be saved in the metadata and that represents
9336 * the custom attributed described by @ctor, @ctorArgs etc.
9337 * Returns: a Byte array representing the blob of data.
9340 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9343 MonoMethodSignature *sig;
9348 MONO_ARCH_SAVE_REGS;
9350 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9351 /* sig is freed later so allocate it in the heap */
9352 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9354 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9357 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9359 p = buffer = g_malloc (buflen);
9360 /* write the prolog */
9363 for (i = 0; i < sig->param_count; ++i) {
9364 arg = mono_array_get (ctorArgs, MonoObject*, i);
9365 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9369 i += mono_array_length (properties);
9371 i += mono_array_length (fields);
9373 *p++ = (i >> 8) & 0xff;
9376 for (i = 0; i < mono_array_length (properties); ++i) {
9380 prop = mono_array_get (properties, gpointer, i);
9381 get_prop_name_and_type (prop, &pname, &ptype);
9382 *p++ = 0x54; /* PROPERTY signature */
9383 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9390 for (i = 0; i < mono_array_length (fields); ++i) {
9394 field = mono_array_get (fields, gpointer, i);
9395 get_field_name_and_type (field, &fname, &ftype);
9396 *p++ = 0x53; /* FIELD signature */
9397 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9402 g_assert (p - buffer <= buflen);
9403 buflen = p - buffer;
9404 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9405 p = mono_array_addr (result, char, 0);
9406 memcpy (p, buffer, buflen);
9408 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9414 * mono_reflection_setup_internal_class:
9415 * @tb: a TypeBuilder object
9417 * Creates a MonoClass that represents the TypeBuilder.
9418 * This is a trick that lets us simplify a lot of reflection code
9419 * (and will allow us to support Build and Run assemblies easier).
9422 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9425 MonoClass *klass, *parent;
9427 MONO_ARCH_SAVE_REGS;
9429 RESOLVE_TYPE (tb->parent);
9431 mono_loader_lock ();
9434 /* check so we can compile corlib correctly */
9435 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9436 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9437 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9439 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9445 /* the type has already being created: it means we just have to change the parent */
9446 if (tb->type.type) {
9447 klass = mono_class_from_mono_type (tb->type.type);
9448 klass->parent = NULL;
9449 /* fool mono_class_setup_parent */
9450 klass->supertypes = NULL;
9451 mono_class_setup_parent (klass, parent);
9452 mono_class_setup_mono_type (klass);
9453 mono_loader_unlock ();
9457 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9459 klass->image = &tb->module->dynamic_image->image;
9461 klass->inited = 1; /* we lie to the runtime */
9462 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9463 if (!mono_error_ok (&error))
9465 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9466 if (!mono_error_ok (&error))
9468 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9469 klass->flags = tb->attrs;
9471 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9473 klass->element_class = klass;
9475 if (klass->reflection_info == NULL) {
9477 MOVING_GC_REGISTER (&klass->reflection_info);
9478 klass->reflection_info = tb;
9480 /* Put into cache so mono_class_get () will find it.
9481 Skip nested types as those should not be available on the global scope. */
9482 if (!tb->nesting_type) {
9483 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9485 klass->image->reflection_info_unregister_classes =
9486 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9489 g_assert (klass->reflection_info == tb);
9492 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9493 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9495 if (parent != NULL) {
9496 mono_class_setup_parent (klass, parent);
9497 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9498 const char *old_n = klass->name;
9499 /* trick to get relative numbering right when compiling corlib */
9500 klass->name = "BuildingObject";
9501 mono_class_setup_parent (klass, mono_defaults.object_class);
9502 klass->name = old_n;
9505 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9506 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9507 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9508 klass->instance_size = sizeof (MonoObject);
9509 klass->size_inited = 1;
9510 mono_class_setup_vtable_general (klass, NULL, 0);
9513 mono_class_setup_mono_type (klass);
9515 mono_class_setup_supertypes (klass);
9518 * FIXME: handle interfaces.
9521 tb->type.type = &klass->byval_arg;
9523 if (tb->nesting_type) {
9524 g_assert (tb->nesting_type->type);
9525 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9528 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9530 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9532 mono_loader_unlock ();
9536 mono_loader_unlock ();
9537 mono_error_raise_exception (&error);
9541 * mono_reflection_setup_generic_class:
9542 * @tb: a TypeBuilder object
9544 * Setup the generic class before adding the first generic parameter.
9547 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9552 * mono_reflection_create_generic_class:
9553 * @tb: a TypeBuilder object
9555 * Creates the generic class after all generic parameters have been added.
9558 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9563 MONO_ARCH_SAVE_REGS;
9565 klass = mono_class_from_mono_type (tb->type.type);
9567 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9569 if (klass->generic_container || (count == 0))
9572 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9574 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9576 klass->generic_container->owner.klass = klass;
9577 klass->generic_container->type_argc = count;
9578 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9580 klass->is_generic = 1;
9582 for (i = 0; i < count; i++) {
9583 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9584 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9585 klass->generic_container->type_params [i] = *param;
9586 /*Make sure we are a diferent type instance */
9587 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9588 klass->generic_container->type_params [i].info.pklass = NULL;
9590 g_assert (klass->generic_container->type_params [i].param.owner);
9593 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9597 * mono_reflection_create_internal_class:
9598 * @tb: a TypeBuilder object
9600 * Actually create the MonoClass that is associated with the TypeBuilder.
9603 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9607 MONO_ARCH_SAVE_REGS;
9609 klass = mono_class_from_mono_type (tb->type.type);
9611 mono_loader_lock ();
9612 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9613 MonoReflectionFieldBuilder *fb;
9615 MonoType *enum_basetype;
9617 g_assert (tb->fields != NULL);
9618 g_assert (mono_array_length (tb->fields) >= 1);
9620 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9622 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9623 mono_loader_unlock ();
9627 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9628 klass->element_class = mono_class_from_mono_type (enum_basetype);
9629 if (!klass->element_class)
9630 klass->element_class = mono_class_from_mono_type (enum_basetype);
9633 * get the element_class from the current corlib.
9635 ec = default_class_from_mono_type (enum_basetype);
9636 klass->instance_size = ec->instance_size;
9637 klass->size_inited = 1;
9639 * this is almost safe to do with enums and it's needed to be able
9640 * to create objects of the enum type (for use in SetConstant).
9642 /* FIXME: Does this mean enums can't have method overrides ? */
9643 mono_class_setup_vtable_general (klass, NULL, 0);
9645 mono_loader_unlock ();
9648 static MonoMarshalSpec*
9649 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9650 MonoReflectionMarshal *minfo)
9652 MonoMarshalSpec *res;
9654 res = image_g_new0 (image, MonoMarshalSpec, 1);
9655 res->native = minfo->type;
9657 switch (minfo->type) {
9658 case MONO_NATIVE_LPARRAY:
9659 res->data.array_data.elem_type = minfo->eltype;
9660 if (minfo->has_size) {
9661 res->data.array_data.param_num = minfo->param_num;
9662 res->data.array_data.num_elem = minfo->count;
9663 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9666 res->data.array_data.param_num = -1;
9667 res->data.array_data.num_elem = -1;
9668 res->data.array_data.elem_mult = -1;
9672 case MONO_NATIVE_BYVALTSTR:
9673 case MONO_NATIVE_BYVALARRAY:
9674 res->data.array_data.num_elem = minfo->count;
9677 case MONO_NATIVE_CUSTOM:
9678 if (minfo->marshaltyperef)
9679 res->data.custom_data.custom_name =
9680 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9682 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9691 #endif /* !DISABLE_REFLECTION_EMIT */
9693 MonoReflectionMarshal*
9694 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9695 MonoMarshalSpec *spec)
9697 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9698 MonoReflectionMarshal *minfo;
9701 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9702 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9703 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9704 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9707 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9708 minfo->type = spec->native;
9710 switch (minfo->type) {
9711 case MONO_NATIVE_LPARRAY:
9712 minfo->eltype = spec->data.array_data.elem_type;
9713 minfo->count = spec->data.array_data.num_elem;
9714 minfo->param_num = spec->data.array_data.param_num;
9717 case MONO_NATIVE_BYVALTSTR:
9718 case MONO_NATIVE_BYVALARRAY:
9719 minfo->count = spec->data.array_data.num_elem;
9722 case MONO_NATIVE_CUSTOM:
9723 if (spec->data.custom_data.custom_name) {
9724 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9726 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9728 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9730 if (spec->data.custom_data.cookie)
9731 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9741 #ifndef DISABLE_REFLECTION_EMIT
9743 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9744 ReflectionMethodBuilder *rmb,
9745 MonoMethodSignature *sig)
9749 MonoMethodNormal *pm;
9750 MonoMarshalSpec **specs;
9751 MonoReflectionMethodAux *method_aux;
9756 mono_error_init (&error);
9758 * Methods created using a MethodBuilder should have their memory allocated
9759 * inside the image mempool, while dynamic methods should have their memory
9762 dynamic = rmb->refs != NULL;
9763 image = dynamic ? NULL : klass->image;
9766 g_assert (!klass->generic_class);
9768 mono_loader_lock ();
9770 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9771 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9772 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9774 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9776 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9778 pm = (MonoMethodNormal*)m;
9780 m->dynamic = dynamic;
9782 m->flags = rmb->attrs;
9783 m->iflags = rmb->iattrs;
9784 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
9785 g_assert (mono_error_ok (&error));
9788 m->skip_visibility = rmb->skip_visibility;
9790 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9792 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9793 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9796 m->signature->pinvoke = 1;
9797 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9798 m->signature->pinvoke = 1;
9800 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9802 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
9803 g_assert (mono_error_ok (&error));
9804 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
9805 g_assert (mono_error_ok (&error));
9807 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9809 if (klass->image->dynamic)
9810 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9812 mono_loader_unlock ();
9815 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9816 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9817 MonoMethodHeader *header;
9819 gint32 max_stack, i;
9820 gint32 num_locals = 0;
9821 gint32 num_clauses = 0;
9825 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9826 code_size = rmb->ilgen->code_len;
9827 max_stack = rmb->ilgen->max_stack;
9828 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9829 if (rmb->ilgen->ex_handlers)
9830 num_clauses = method_count_clauses (rmb->ilgen);
9833 code = mono_array_addr (rmb->code, guint8, 0);
9834 code_size = mono_array_length (rmb->code);
9835 /* we probably need to run a verifier on the code... */
9845 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9846 header->code_size = code_size;
9847 header->code = image_g_malloc (image, code_size);
9848 memcpy ((char*)header->code, code, code_size);
9849 header->max_stack = max_stack;
9850 header->init_locals = rmb->init_locals;
9851 header->num_locals = num_locals;
9853 for (i = 0; i < num_locals; ++i) {
9854 MonoReflectionLocalBuilder *lb =
9855 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9857 header->locals [i] = image_g_new0 (image, MonoType, 1);
9858 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9861 header->num_clauses = num_clauses;
9863 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9864 rmb->ilgen, num_clauses);
9867 pm->header = header;
9870 if (rmb->generic_params) {
9871 int count = mono_array_length (rmb->generic_params);
9872 MonoGenericContainer *container;
9874 container = rmb->generic_container;
9876 m->is_generic = TRUE;
9877 mono_method_set_generic_container (m, container);
9879 container->type_argc = count;
9880 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9881 container->owner.method = m;
9883 for (i = 0; i < count; i++) {
9884 MonoReflectionGenericParam *gp =
9885 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9886 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9887 container->type_params [i] = *param;
9890 if (klass->generic_container) {
9891 container->parent = klass->generic_container;
9892 container->context.class_inst = klass->generic_container->context.class_inst;
9894 container->context.method_inst = mono_get_shared_generic_inst (container);
9898 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9902 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9904 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9905 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9906 for (i = 0; i < rmb->nrefs; ++i)
9907 data [i + 1] = rmb->refs [i];
9912 /* Parameter info */
9915 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9916 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9917 for (i = 0; i <= m->signature->param_count; ++i) {
9918 MonoReflectionParamBuilder *pb;
9919 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9920 if ((i > 0) && (pb->attrs)) {
9921 /* Make a copy since it might point to a shared type structure */
9922 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9923 m->signature->params [i - 1]->attrs = pb->attrs;
9926 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9927 MonoDynamicImage *assembly;
9928 guint32 idx, def_type, len;
9932 if (!method_aux->param_defaults) {
9933 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9934 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9936 assembly = (MonoDynamicImage*)klass->image;
9937 idx = encode_constant (assembly, pb->def_value, &def_type);
9938 /* Copy the data from the blob since it might get realloc-ed */
9939 p = assembly->blob.data + idx;
9940 len = mono_metadata_decode_blob_size (p, &p2);
9942 method_aux->param_defaults [i] = image_g_malloc (image, len);
9943 method_aux->param_default_types [i] = def_type;
9944 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9948 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
9949 g_assert (mono_error_ok (&error));
9952 if (!method_aux->param_cattr)
9953 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9954 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9960 /* Parameter marshalling */
9963 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9964 MonoReflectionParamBuilder *pb;
9965 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9966 if (pb->marshal_info) {
9968 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9969 specs [pb->position] =
9970 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9974 if (specs != NULL) {
9976 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9977 method_aux->param_marshall = specs;
9980 if (klass->image->dynamic && method_aux)
9981 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9983 mono_loader_unlock ();
9989 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9991 ReflectionMethodBuilder rmb;
9992 MonoMethodSignature *sig;
9994 mono_loader_lock ();
9995 sig = ctor_builder_to_signature (klass->image, mb);
9996 mono_loader_unlock ();
9998 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10000 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10001 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10003 /* If we are in a generic class, we might be called multiple times from inflate_method */
10004 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10005 /* ilgen is no longer needed */
10009 return mb->mhandle;
10013 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10015 ReflectionMethodBuilder rmb;
10016 MonoMethodSignature *sig;
10018 mono_loader_lock ();
10019 sig = method_builder_to_signature (klass->image, mb);
10020 mono_loader_unlock ();
10022 reflection_methodbuilder_from_method_builder (&rmb, mb);
10024 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10025 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10027 /* If we are in a generic class, we might be called multiple times from inflate_method */
10028 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10029 /* ilgen is no longer needed */
10032 return mb->mhandle;
10035 static MonoClassField*
10036 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10038 MonoClassField *field;
10041 field = g_new0 (MonoClassField, 1);
10043 field->name = mono_string_to_utf8 (fb->name);
10044 if (fb->attrs || fb->modreq || fb->modopt) {
10045 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10046 field->type->attrs = fb->attrs;
10048 g_assert (klass->image->dynamic);
10049 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10050 g_free (field->type);
10051 field->type = custom;
10053 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10055 if (fb->offset != -1)
10056 field->offset = fb->offset;
10057 field->parent = klass;
10058 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10060 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10067 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10070 MonoReflectionTypeBuilder *tb = NULL;
10071 gboolean is_dynamic = FALSE;
10072 MonoDomain *domain;
10073 MonoClass *geninst;
10075 mono_loader_lock ();
10077 domain = mono_object_domain (type);
10079 if (is_sre_type_builder (mono_object_class (type))) {
10080 tb = (MonoReflectionTypeBuilder *) type;
10083 } else if (is_sre_generic_instance (mono_object_class (type))) {
10084 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10085 MonoReflectionType *gtd = rgi->generic_type;
10087 if (is_sre_type_builder (mono_object_class (gtd))) {
10088 tb = (MonoReflectionTypeBuilder *)gtd;
10093 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10094 if (tb && tb->generic_container)
10095 mono_reflection_create_generic_class (tb);
10097 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10098 if (!klass->generic_container) {
10099 mono_loader_unlock ();
10103 if (klass->wastypebuilder) {
10104 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
10109 mono_loader_unlock ();
10111 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10113 return &geninst->byval_arg;
10117 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10119 MonoGenericClass *gclass;
10120 MonoGenericInst *inst;
10122 g_assert (klass->generic_container);
10124 inst = mono_metadata_get_generic_inst (type_argc, types);
10125 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10127 return mono_generic_class_get_class (gclass);
10130 MonoReflectionMethod*
10131 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10134 MonoMethod *method, *inflated;
10135 MonoMethodInflated *imethod;
10136 MonoGenericContext tmp_context;
10137 MonoGenericInst *ginst;
10138 MonoType **type_argv;
10141 MONO_ARCH_SAVE_REGS;
10143 /*FIXME but this no longer should happen*/
10144 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10145 #ifndef DISABLE_REFLECTION_EMIT
10146 MonoReflectionMethodBuilder *mb = NULL;
10147 MonoReflectionTypeBuilder *tb;
10150 mb = (MonoReflectionMethodBuilder *) rmethod;
10151 tb = (MonoReflectionTypeBuilder *) mb->type;
10152 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10154 method = methodbuilder_to_mono_method (klass, mb);
10156 g_assert_not_reached ();
10160 method = rmethod->method;
10163 klass = method->klass;
10165 if (method->is_inflated)
10166 method = ((MonoMethodInflated *) method)->declaring;
10168 count = mono_method_signature (method)->generic_param_count;
10169 if (count != mono_array_length (types))
10172 type_argv = g_new0 (MonoType *, count);
10173 for (i = 0; i < count; i++) {
10174 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10175 type_argv [i] = mono_reflection_type_get_handle (garg);
10177 ginst = mono_metadata_get_generic_inst (count, type_argv);
10178 g_free (type_argv);
10180 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10181 tmp_context.method_inst = ginst;
10183 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10184 imethod = (MonoMethodInflated *) inflated;
10186 /*FIXME but I think this is no longer necessary*/
10187 if (method->klass->image->dynamic) {
10188 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10190 * This table maps metadata structures representing inflated methods/fields
10191 * to the reflection objects representing their generic definitions.
10193 mono_loader_lock ();
10194 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10195 mono_loader_unlock ();
10198 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10201 #ifndef DISABLE_REFLECTION_EMIT
10203 static MonoMethod *
10204 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10206 MonoMethodInflated *imethod;
10207 MonoGenericContext *context;
10211 * With generic code sharing the klass might not be inflated.
10212 * This can happen because classes inflated with their own
10213 * type arguments are "normalized" to the uninflated class.
10215 if (!klass->generic_class)
10218 context = mono_class_get_context (klass);
10220 if (klass->method.count) {
10221 /* Find the already created inflated method */
10222 for (i = 0; i < klass->method.count; ++i) {
10223 g_assert (klass->methods [i]->is_inflated);
10224 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10227 g_assert (i < klass->method.count);
10228 imethod = (MonoMethodInflated*)klass->methods [i];
10230 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10233 if (method->is_generic && method->klass->image->dynamic) {
10234 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10236 mono_loader_lock ();
10237 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10238 mono_loader_unlock ();
10240 return (MonoMethod *) imethod;
10243 static MonoMethod *
10244 inflate_method (MonoReflectionType *type, MonoObject *obj)
10246 MonoMethod *method;
10249 MonoClass *type_class = mono_object_class (type);
10251 if (is_sre_generic_instance (type_class)) {
10252 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10253 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10254 } else if (is_sre_type_builder (type_class)) {
10255 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10256 } else if (type->type) {
10257 gklass = mono_class_from_mono_type (type->type);
10258 gklass = mono_class_get_generic_type_definition (gklass);
10260 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10263 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10264 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10265 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10267 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10268 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10269 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10270 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10271 method = ((MonoReflectionMethod *) obj)->method;
10273 method = NULL; /* prevent compiler warning */
10274 g_error ("can't handle type %s", obj->vtable->klass->name);
10277 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10280 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10282 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10283 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10286 MonoGenericClass *gclass;
10287 MonoDynamicGenericClass *dgclass;
10288 MonoClass *klass, *gklass;
10292 MONO_ARCH_SAVE_REGS;
10294 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10295 klass = mono_class_from_mono_type (gtype);
10296 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10297 gclass = gtype->data.generic_class;
10299 if (!gclass->is_dynamic)
10302 dgclass = (MonoDynamicGenericClass *) gclass;
10304 if (dgclass->initialized)
10307 gklass = gclass->container_class;
10308 mono_class_init (gklass);
10310 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10311 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10312 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10313 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
10314 dgclass->count_events = events ? mono_array_length (events) : 0;
10316 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10317 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10318 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10319 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
10320 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
10321 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10322 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10324 for (i = 0; i < dgclass->count_methods; i++) {
10325 MonoObject *obj = mono_array_get (methods, gpointer, i);
10327 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10330 for (i = 0; i < dgclass->count_ctors; i++) {
10331 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10333 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10336 for (i = 0; i < dgclass->count_fields; i++) {
10337 MonoObject *obj = mono_array_get (fields, gpointer, i);
10338 MonoClassField *field, *inflated_field = NULL;
10340 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10341 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10342 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10343 field = ((MonoReflectionField *) obj)->field;
10345 field = NULL; /* prevent compiler warning */
10346 g_assert_not_reached ();
10349 dgclass->fields [i] = *field;
10350 dgclass->fields [i].parent = klass;
10351 dgclass->fields [i].type = mono_class_inflate_generic_type (
10352 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10353 dgclass->field_generic_types [i] = field->type;
10354 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10355 dgclass->field_objects [i] = obj;
10357 if (inflated_field) {
10358 g_free (inflated_field);
10360 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10364 for (i = 0; i < dgclass->count_properties; i++) {
10365 MonoObject *obj = mono_array_get (properties, gpointer, i);
10366 MonoProperty *property = &dgclass->properties [i];
10368 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
10369 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
10371 property->parent = klass;
10372 property->attrs = pb->attrs;
10373 property->name = mono_string_to_utf8 (pb->name);
10374 if (pb->get_method)
10375 property->get = inflate_method ((MonoReflectionType*)type, (MonoObject *) pb->get_method);
10376 if (pb->set_method)
10377 property->set = inflate_method ((MonoReflectionType*)type, (MonoObject *) pb->set_method);
10378 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
10379 *property = *((MonoReflectionProperty *) obj)->property;
10380 property->name = g_strdup (property->name);
10383 property->get = inflate_mono_method (klass, property->get, NULL);
10385 property->set = inflate_mono_method (klass, property->set, NULL);
10387 g_assert_not_reached ();
10390 for (i = 0; i < dgclass->count_events; i++) {
10391 MonoObject *obj = mono_array_get (events, gpointer, i);
10392 MonoEvent *event = &dgclass->events [i];
10394 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
10395 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
10397 event->parent = klass;
10398 event->attrs = eb->attrs;
10399 event->name = mono_string_to_utf8 (eb->name);
10400 if (eb->add_method)
10401 event->add = inflate_method ((MonoReflectionType*)type, (MonoObject *) eb->add_method);
10402 if (eb->remove_method)
10403 event->remove = inflate_method ((MonoReflectionType*)type, (MonoObject *) eb->remove_method);
10404 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
10405 *event = *((MonoReflectionMonoEvent *) obj)->event;
10406 event->name = g_strdup (event->name);
10409 event->add = inflate_mono_method (klass, event->add, NULL);
10411 event->remove = inflate_mono_method (klass, event->remove, NULL);
10413 g_assert_not_reached ();
10416 dgclass->initialized = TRUE;
10420 fix_partial_generic_class (MonoClass *klass)
10422 MonoClass *gklass = klass->generic_class->container_class;
10423 MonoDynamicGenericClass *dgclass;
10426 if (klass->wastypebuilder)
10429 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10431 if (!dgclass->initialized)
10434 if (klass->method.count != gklass->method.count) {
10435 klass->method.count = gklass->method.count;
10436 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10438 for (i = 0; i < klass->method.count; i++) {
10439 klass->methods [i] = mono_class_inflate_generic_method_full (
10440 gklass->methods [i], klass, mono_class_get_context (klass));
10444 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10445 klass->interface_count = gklass->interface_count;
10446 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10447 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10449 for (i = 0; i < gklass->interface_count; ++i) {
10450 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10451 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10452 mono_metadata_free_type (iface_type);
10454 ensure_runtime_vtable (klass->interfaces [i]);
10456 klass->interfaces_inited = 1;
10459 if (klass->field.count != gklass->field.count) {
10460 klass->field.count = gklass->field.count;
10461 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10463 for (i = 0; i < klass->field.count; i++) {
10464 klass->fields [i] = gklass->fields [i];
10465 klass->fields [i].parent = klass;
10466 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10470 /*We can only finish with this klass once it's parent has as well*/
10471 if (gklass->wastypebuilder)
10472 klass->wastypebuilder = TRUE;
10477 ensure_generic_class_runtime_vtable (MonoClass *klass)
10479 MonoClass *gklass = klass->generic_class->container_class;
10481 ensure_runtime_vtable (gklass);
10483 fix_partial_generic_class (klass);
10487 ensure_runtime_vtable (MonoClass *klass)
10489 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10492 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10495 ensure_runtime_vtable (klass->parent);
10498 num = tb->ctors? mono_array_length (tb->ctors): 0;
10499 num += tb->num_methods;
10500 klass->method.count = num;
10501 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10502 num = tb->ctors? mono_array_length (tb->ctors): 0;
10503 for (i = 0; i < num; ++i)
10504 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10505 num = tb->num_methods;
10507 for (i = 0; i < num; ++i)
10508 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10510 if (tb->interfaces) {
10511 klass->interface_count = mono_array_length (tb->interfaces);
10512 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10513 for (i = 0; i < klass->interface_count; ++i) {
10514 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10515 klass->interfaces [i] = mono_class_from_mono_type (iface);
10516 ensure_runtime_vtable (klass->interfaces [i]);
10518 klass->interfaces_inited = 1;
10520 } else if (klass->generic_class){
10521 ensure_generic_class_runtime_vtable (klass);
10524 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10525 for (i = 0; i < klass->method.count; ++i)
10526 klass->methods [i]->slot = i;
10528 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10529 mono_class_setup_interface_offsets (klass);
10530 mono_class_setup_interface_id (klass);
10534 * The generic vtable is needed even if image->run is not set since some
10535 * runtime code like ves_icall_Type_GetMethodsByName depends on
10536 * method->slot being defined.
10540 * tb->methods could not be freed since it is used for determining
10541 * overrides during dynamic vtable construction.
10546 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10548 MonoReflectionTypeBuilder *tb;
10552 *num_overrides = 0;
10554 g_assert (klass->image->dynamic);
10556 if (!klass->reflection_info)
10559 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10561 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10565 for (i = 0; i < tb->num_methods; ++i) {
10566 MonoReflectionMethodBuilder *mb =
10567 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10568 if (mb->override_method)
10574 *overrides = g_new0 (MonoMethod*, onum * 2);
10577 for (i = 0; i < tb->num_methods; ++i) {
10578 MonoReflectionMethodBuilder *mb =
10579 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10580 if (mb->override_method) {
10581 (*overrides) [onum * 2] =
10582 mb->override_method->method;
10583 (*overrides) [onum * 2 + 1] =
10586 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10587 g_assert (mb->override_method->method);
10588 g_assert (mb->mhandle);
10595 *num_overrides = onum;
10599 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10601 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10602 MonoReflectionFieldBuilder *fb;
10603 MonoClassField *field;
10604 MonoImage *image = klass->image;
10605 const char *p, *p2;
10607 guint32 len, idx, real_size = 0;
10609 klass->field.count = tb->num_fields;
10610 klass->field.first = 0;
10612 mono_error_init (error);
10614 if (tb->class_size) {
10615 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10616 klass->packing_size = tb->packing_size;
10617 real_size = klass->instance_size + tb->class_size;
10620 if (!klass->field.count) {
10621 klass->instance_size = MAX (klass->instance_size, real_size);
10625 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10626 mono_class_alloc_ext (klass);
10627 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10629 for (i = 0; i < klass->field.count; ++i) {
10630 fb = mono_array_get (tb->fields, gpointer, i);
10631 field = &klass->fields [i];
10632 field->name = mono_string_to_utf8_image (image, fb->name, error);
10633 if (!mono_error_ok (error))
10636 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10637 field->type->attrs = fb->attrs;
10639 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10641 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10642 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10643 if (fb->offset != -1)
10644 field->offset = fb->offset;
10645 field->parent = klass;
10646 fb->handle = field;
10647 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10649 if (fb->def_value) {
10650 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10651 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10652 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10653 /* Copy the data from the blob since it might get realloc-ed */
10654 p = assembly->blob.data + idx;
10655 len = mono_metadata_decode_blob_size (p, &p2);
10657 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10658 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10662 klass->instance_size = MAX (klass->instance_size, real_size);
10663 mono_class_layout_fields (klass);
10667 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10669 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10670 MonoReflectionPropertyBuilder *pb;
10671 MonoImage *image = klass->image;
10672 MonoProperty *properties;
10675 mono_error_init (error);
10678 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10680 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10681 klass->ext->property.first = 0;
10683 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10684 klass->ext->properties = properties;
10685 for (i = 0; i < klass->ext->property.count; ++i) {
10686 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10687 properties [i].parent = klass;
10688 properties [i].attrs = pb->attrs;
10689 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10690 if (!mono_error_ok (error))
10692 if (pb->get_method)
10693 properties [i].get = pb->get_method->mhandle;
10694 if (pb->set_method)
10695 properties [i].set = pb->set_method->mhandle;
10697 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10701 MonoReflectionEvent *
10702 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10704 MonoEvent *event = g_new0 (MonoEvent, 1);
10708 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10710 event->parent = klass;
10711 event->attrs = eb->attrs;
10712 event->name = mono_string_to_utf8 (eb->name);
10713 if (eb->add_method)
10714 event->add = eb->add_method->mhandle;
10715 if (eb->remove_method)
10716 event->remove = eb->remove_method->mhandle;
10717 if (eb->raise_method)
10718 event->raise = eb->raise_method->mhandle;
10720 if (eb->other_methods) {
10721 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10722 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10723 MonoReflectionMethodBuilder *mb =
10724 mono_array_get (eb->other_methods,
10725 MonoReflectionMethodBuilder*, j);
10726 event->other [j] = mb->mhandle;
10730 return mono_event_get_object (mono_object_domain (tb), klass, event);
10734 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10736 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10737 MonoReflectionEventBuilder *eb;
10738 MonoImage *image = klass->image;
10742 mono_error_init (error);
10745 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10747 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10748 klass->ext->event.first = 0;
10750 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10751 klass->ext->events = events;
10752 for (i = 0; i < klass->ext->event.count; ++i) {
10753 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10754 events [i].parent = klass;
10755 events [i].attrs = eb->attrs;
10756 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10757 if (!mono_error_ok (error))
10759 if (eb->add_method)
10760 events [i].add = eb->add_method->mhandle;
10761 if (eb->remove_method)
10762 events [i].remove = eb->remove_method->mhandle;
10763 if (eb->raise_method)
10764 events [i].raise = eb->raise_method->mhandle;
10766 if (eb->other_methods) {
10767 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10768 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10769 MonoReflectionMethodBuilder *mb =
10770 mono_array_get (eb->other_methods,
10771 MonoReflectionMethodBuilder*, j);
10772 events [i].other [j] = mb->mhandle;
10775 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10780 remove_instantiations_of_and_ensure_contents (gpointer key,
10782 gpointer user_data)
10784 MonoType *type = (MonoType*)key;
10785 MonoClass *klass = (MonoClass*)user_data;
10787 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
10788 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
10795 check_array_for_usertypes (MonoArray *arr)
10802 for (i = 0; i < mono_array_length (arr); ++i)
10803 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10806 MonoReflectionType*
10807 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10811 MonoDomain* domain;
10812 MonoReflectionType* res;
10815 MONO_ARCH_SAVE_REGS;
10817 domain = mono_object_domain (tb);
10818 klass = mono_class_from_mono_type (tb->type.type);
10821 * Check for user defined Type subclasses.
10823 RESOLVE_TYPE (tb->parent);
10824 check_array_for_usertypes (tb->interfaces);
10826 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10827 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10829 RESOLVE_TYPE (fb->type);
10830 check_array_for_usertypes (fb->modreq);
10831 check_array_for_usertypes (fb->modopt);
10832 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10833 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10838 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10839 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10841 RESOLVE_TYPE (mb->rtype);
10842 check_array_for_usertypes (mb->return_modreq);
10843 check_array_for_usertypes (mb->return_modopt);
10844 check_array_for_usertypes (mb->parameters);
10845 if (mb->param_modreq)
10846 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10847 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10848 if (mb->param_modopt)
10849 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10850 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10855 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10856 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10858 check_array_for_usertypes (mb->parameters);
10859 if (mb->param_modreq)
10860 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10861 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10862 if (mb->param_modopt)
10863 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10864 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10869 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10872 * we need to lock the domain because the lock will be taken inside
10873 * So, we need to keep the locking order correct.
10875 mono_loader_lock ();
10876 mono_domain_lock (domain);
10877 if (klass->wastypebuilder) {
10878 mono_domain_unlock (domain);
10879 mono_loader_unlock ();
10880 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10883 * Fields to set in klass:
10884 * the various flags: delegate/unicode/contextbound etc.
10886 klass->flags = tb->attrs;
10887 klass->has_cctor = 1;
10888 klass->has_finalize = 1;
10891 if (!((MonoDynamicImage*)klass->image)->run) {
10892 if (klass->generic_container) {
10893 /* FIXME: The code below can't handle generic classes */
10894 klass->wastypebuilder = TRUE;
10895 mono_loader_unlock ();
10896 mono_domain_unlock (domain);
10897 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10902 /* enums are done right away */
10903 if (!klass->enumtype)
10904 ensure_runtime_vtable (klass);
10906 if (tb->subtypes) {
10907 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10908 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10909 mono_class_alloc_ext (klass);
10910 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)));
10914 klass->nested_classes_inited = TRUE;
10916 /* fields and object layout */
10917 if (klass->parent) {
10918 if (!klass->parent->size_inited)
10919 mono_class_init (klass->parent);
10920 klass->instance_size = klass->parent->instance_size;
10921 klass->sizes.class_size = 0;
10922 klass->min_align = klass->parent->min_align;
10923 /* if the type has no fields we won't call the field_setup
10924 * routine which sets up klass->has_references.
10926 klass->has_references |= klass->parent->has_references;
10928 klass->instance_size = sizeof (MonoObject);
10929 klass->min_align = 1;
10932 /* FIXME: handle packing_size and instance_size */
10933 typebuilder_setup_fields (klass, &error);
10934 if (!mono_error_ok (&error))
10936 typebuilder_setup_properties (klass, &error);
10937 if (!mono_error_ok (&error))
10940 typebuilder_setup_events (klass, &error);
10941 if (!mono_error_ok (&error))
10944 klass->wastypebuilder = TRUE;
10947 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10948 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10949 * we want to return normal System.MonoType objects, so clear these out from the cache.
10951 * Together with this we must ensure the contents of all instances to match the created type.
10953 if (domain->type_hash && klass->generic_container)
10954 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
10956 mono_domain_unlock (domain);
10957 mono_loader_unlock ();
10959 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10960 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10961 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10964 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10965 g_assert (res != (MonoReflectionType*)tb);
10970 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10971 klass->wastypebuilder = TRUE;
10972 mono_domain_unlock (domain);
10973 mono_loader_unlock ();
10974 mono_error_raise_exception (&error);
10979 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10981 MonoGenericParamFull *param;
10985 MONO_ARCH_SAVE_REGS;
10987 param = g_new0 (MonoGenericParamFull, 1);
10989 if (gparam->mbuilder) {
10990 if (!gparam->mbuilder->generic_container) {
10991 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10992 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10993 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10994 gparam->mbuilder->generic_container->is_method = TRUE;
10996 * Cannot set owner.method, since the MonoMethod is not created yet.
10997 * Set the image field instead, so type_in_image () works.
10999 gparam->mbuilder->generic_container->image = klass->image;
11001 param->param.owner = gparam->mbuilder->generic_container;
11002 } else if (gparam->tbuilder) {
11003 if (!gparam->tbuilder->generic_container) {
11004 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11005 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11006 gparam->tbuilder->generic_container->owner.klass = klass;
11008 param->param.owner = gparam->tbuilder->generic_container;
11011 param->info.name = mono_string_to_utf8 (gparam->name);
11012 param->param.num = gparam->index;
11014 image = &gparam->tbuilder->module->dynamic_image->image;
11015 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11017 gparam->type.type = &pklass->byval_arg;
11019 MOVING_GC_REGISTER (&pklass->reflection_info);
11020 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
11021 mono_image_lock (image);
11022 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11023 mono_image_unlock (image);
11027 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11029 MonoReflectionModuleBuilder *module = sig->module;
11030 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11031 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11036 check_array_for_usertypes (sig->arguments);
11038 sigbuffer_init (&buf, 32);
11040 sigbuffer_add_value (&buf, 0x07);
11041 sigbuffer_add_value (&buf, na);
11042 if (assembly != NULL){
11043 for (i = 0; i < na; ++i) {
11044 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11045 encode_reflection_type (assembly, type, &buf);
11049 buflen = buf.p - buf.buf;
11050 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11051 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11052 sigbuffer_free (&buf);
11058 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11060 MonoDynamicImage *assembly = sig->module->dynamic_image;
11061 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11066 check_array_for_usertypes (sig->arguments);
11068 sigbuffer_init (&buf, 32);
11070 sigbuffer_add_value (&buf, 0x06);
11071 for (i = 0; i < na; ++i) {
11072 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11073 encode_reflection_type (assembly, type, &buf);
11076 buflen = buf.p - buf.buf;
11077 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11078 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11079 sigbuffer_free (&buf);
11085 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11087 ReflectionMethodBuilder rmb;
11088 MonoMethodSignature *sig;
11093 sig = dynamic_method_to_signature (mb);
11095 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11098 * Resolve references.
11101 * Every second entry in the refs array is reserved for storing handle_class,
11102 * which is needed by the ldtoken implementation in the JIT.
11104 rmb.nrefs = mb->nrefs;
11105 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11106 for (i = 0; i < mb->nrefs; i += 2) {
11107 MonoClass *handle_class;
11109 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11111 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11112 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11114 * The referenced DynamicMethod should already be created by the managed
11115 * code, except in the case of circular references. In that case, we store
11116 * method in the refs array, and fix it up later when the referenced
11117 * DynamicMethod is created.
11119 if (method->mhandle) {
11120 ref = method->mhandle;
11122 /* FIXME: GC object stored in unmanaged memory */
11125 /* FIXME: GC object stored in unmanaged memory */
11126 method->referenced_by = g_slist_append (method->referenced_by, mb);
11128 handle_class = mono_defaults.methodhandle_class;
11130 MonoException *ex = NULL;
11131 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11133 ex = mono_get_exception_type_load (NULL, NULL);
11134 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11135 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11139 mono_raise_exception (ex);
11144 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11145 rmb.refs [i + 1] = handle_class;
11148 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11150 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11152 /* Fix up refs entries pointing at us */
11153 for (l = mb->referenced_by; l; l = l->next) {
11154 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11155 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11158 g_assert (method->mhandle);
11160 data = (gpointer*)wrapper->method_data;
11161 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11162 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11163 data [i + 1] = mb->mhandle;
11166 g_slist_free (mb->referenced_by);
11170 /* ilgen is no longer needed */
11174 #endif /* DISABLE_REFLECTION_EMIT */
11177 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11182 mono_runtime_free_method (
11183 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11188 * mono_reflection_is_valid_dynamic_token:
11190 * Returns TRUE if token is valid.
11194 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11196 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11199 #ifndef DISABLE_REFLECTION_EMIT
11202 * mono_reflection_lookup_dynamic_token:
11204 * Finish the Builder object pointed to by TOKEN and return the corresponding
11205 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11206 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11209 * LOCKING: Take the loader lock
11212 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11214 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11218 mono_loader_lock ();
11219 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11220 mono_loader_unlock ();
11223 g_error ("Could not find required dynamic token 0x%08x", token);
11229 handle_class = &klass;
11230 return resolve_object (image, obj, handle_class, context);
11234 * ensure_complete_type:
11236 * Ensure that KLASS is completed if it is a dynamic type, or references
11240 ensure_complete_type (MonoClass *klass)
11242 if (klass->image->dynamic && !klass->wastypebuilder) {
11243 MonoReflectionTypeBuilder *tb = klass->reflection_info;
11245 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11247 // Asserting here could break a lot of code
11248 //g_assert (klass->wastypebuilder);
11251 if (klass->generic_class) {
11252 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11255 for (i = 0; i < inst->type_argc; ++i) {
11256 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11262 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11264 gpointer result = NULL;
11266 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11267 result = mono_string_intern ((MonoString*)obj);
11268 *handle_class = mono_defaults.string_class;
11270 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11271 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11273 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11274 result = mono_class_from_mono_type (inflated);
11275 mono_metadata_free_type (inflated);
11277 result = mono_class_from_mono_type (type);
11279 *handle_class = mono_defaults.typehandle_class;
11281 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11282 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11283 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11284 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11285 result = ((MonoReflectionMethod*)obj)->method;
11287 result = mono_class_inflate_generic_method (result, context);
11288 *handle_class = mono_defaults.methodhandle_class;
11290 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11291 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11292 result = mb->mhandle;
11294 /* Type is not yet created */
11295 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11297 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11300 * Hopefully this has been filled in by calling CreateType() on the
11304 * TODO: This won't work if the application finishes another
11305 * TypeBuilder instance instead of this one.
11307 result = mb->mhandle;
11310 result = mono_class_inflate_generic_method (result, context);
11311 *handle_class = mono_defaults.methodhandle_class;
11312 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11313 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11315 result = cb->mhandle;
11317 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11319 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11320 result = cb->mhandle;
11323 result = mono_class_inflate_generic_method (result, context);
11324 *handle_class = mono_defaults.methodhandle_class;
11325 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11326 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11328 ensure_complete_type (field->parent);
11330 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11331 MonoClass *class = mono_class_from_mono_type (inflated);
11332 MonoClassField *inflated_field;
11333 gpointer iter = NULL;
11334 mono_metadata_free_type (inflated);
11335 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11336 if (!strcmp (field->name, inflated_field->name))
11339 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11340 result = inflated_field;
11344 *handle_class = mono_defaults.fieldhandle_class;
11346 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11347 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11348 result = fb->handle;
11351 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11353 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11354 result = fb->handle;
11357 if (fb->handle && fb->handle->parent->generic_container) {
11358 MonoClass *klass = fb->handle->parent;
11359 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11360 MonoClass *inflated = mono_class_from_mono_type (type);
11362 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11364 mono_metadata_free_type (type);
11366 *handle_class = mono_defaults.fieldhandle_class;
11367 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11368 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11369 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11372 klass = type->data.klass;
11373 if (klass->wastypebuilder) {
11374 /* Already created */
11378 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11379 result = type->data.klass;
11382 *handle_class = mono_defaults.typehandle_class;
11383 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11384 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11385 MonoMethodSignature *sig;
11388 if (helper->arguments)
11389 nargs = mono_array_length (helper->arguments);
11393 sig = mono_metadata_signature_alloc (image, nargs);
11394 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11395 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11397 if (helper->call_conv == 0) /* unmanaged */
11398 sig->call_convention = helper->unmanaged_call_conv - 1;
11400 if (helper->call_conv & 0x02)
11401 sig->call_convention = MONO_CALL_VARARG;
11403 sig->call_convention = MONO_CALL_DEFAULT;
11405 sig->param_count = nargs;
11406 /* TODO: Copy type ? */
11407 sig->ret = helper->return_type->type;
11408 for (i = 0; i < nargs; ++i)
11409 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11412 *handle_class = NULL;
11413 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11414 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11415 /* Already created by the managed code */
11416 g_assert (method->mhandle);
11417 result = method->mhandle;
11418 *handle_class = mono_defaults.methodhandle_class;
11419 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11420 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11421 type = mono_class_inflate_generic_type (type, context);
11422 result = mono_class_from_mono_type (type);
11423 *handle_class = mono_defaults.typehandle_class;
11425 mono_metadata_free_type (type);
11426 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11427 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11428 type = mono_class_inflate_generic_type (type, context);
11429 result = mono_class_from_mono_type (type);
11430 *handle_class = mono_defaults.typehandle_class;
11432 mono_metadata_free_type (type);
11433 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11434 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11435 MonoClass *inflated;
11437 MonoClassField *field;
11439 if (is_sre_field_builder (mono_object_class (f->fb)))
11440 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11441 else if (is_sr_mono_field (mono_object_class (f->fb)))
11442 field = ((MonoReflectionField*)f->fb)->field;
11444 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
11446 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11447 inflated = mono_class_from_mono_type (type);
11449 result = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11451 mono_metadata_free_type (type);
11452 *handle_class = mono_defaults.fieldhandle_class;
11453 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11454 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11455 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11456 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11457 MonoMethod *method;
11459 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11460 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11461 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11462 method = ((MonoReflectionMethod *)c->cb)->method;
11464 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
11466 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11467 *handle_class = mono_defaults.methodhandle_class;
11468 mono_metadata_free_type (type);
11469 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11470 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11471 if (m->method_args) {
11472 result = mono_reflection_method_on_tb_inst_get_handle (m);
11474 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11475 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11476 MonoMethod *method;
11478 if (is_sre_method_builder (mono_object_class (m->mb)))
11479 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11480 else if (is_sr_mono_method (mono_object_class (m->mb)))
11481 method = ((MonoReflectionMethod *)m->mb)->method;
11483 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11485 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11486 mono_metadata_free_type (type);
11488 *handle_class = mono_defaults.methodhandle_class;
11489 } else if (is_sre_array (mono_object_get_class(obj)) ||
11490 is_sre_byref (mono_object_get_class(obj)) ||
11491 is_sre_pointer (mono_object_get_class(obj))) {
11492 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11493 MonoType *type = mono_reflection_type_get_handle (ref_type);
11494 result = mono_class_from_mono_type (type);
11495 *handle_class = mono_defaults.typehandle_class;
11497 g_print ("%s\n", obj->vtable->klass->name);
11498 g_assert_not_reached ();
11503 #else /* DISABLE_REFLECTION_EMIT */
11506 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11508 g_assert_not_reached ();
11513 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11515 g_assert_not_reached ();
11519 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11521 g_assert_not_reached ();
11525 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11527 g_assert_not_reached ();
11531 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11533 g_assert_not_reached ();
11537 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11539 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11543 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11545 g_assert_not_reached ();
11549 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11551 g_assert_not_reached ();
11554 MonoReflectionModule *
11555 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11557 g_assert_not_reached ();
11562 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11564 g_assert_not_reached ();
11569 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11571 g_assert_not_reached ();
11576 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11577 gboolean create_methodspec, gboolean register_token)
11579 g_assert_not_reached ();
11584 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11589 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11590 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11593 g_assert_not_reached ();
11597 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11600 *num_overrides = 0;
11603 MonoReflectionEvent *
11604 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11606 g_assert_not_reached ();
11610 MonoReflectionType*
11611 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11613 g_assert_not_reached ();
11618 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11620 g_assert_not_reached ();
11624 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11626 g_assert_not_reached ();
11631 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11633 g_assert_not_reached ();
11638 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11643 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11649 mono_reflection_type_get_handle (MonoReflectionType* ref)
11656 #endif /* DISABLE_REFLECTION_EMIT */
11658 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11659 const static guint32 declsec_flags_map[] = {
11660 0x00000000, /* empty */
11661 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11662 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11663 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11664 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11665 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11666 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11667 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11668 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11669 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11670 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11671 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11672 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11673 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11674 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11675 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11676 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11677 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11678 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11682 * Returns flags that includes all available security action associated to the handle.
11683 * @token: metadata token (either for a class or a method)
11684 * @image: image where resides the metadata.
11687 mono_declsec_get_flags (MonoImage *image, guint32 token)
11689 int index = mono_metadata_declsec_from_index (image, token);
11690 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11691 guint32 result = 0;
11695 /* HasSecurity can be present for other, not specially encoded, attributes,
11696 e.g. SuppressUnmanagedCodeSecurityAttribute */
11700 for (i = index; i < t->rows; i++) {
11701 guint32 cols [MONO_DECL_SECURITY_SIZE];
11703 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11704 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11707 action = cols [MONO_DECL_SECURITY_ACTION];
11708 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11709 result |= declsec_flags_map [action];
11711 g_assert_not_reached ();
11718 * Get the security actions (in the form of flags) associated with the specified method.
11720 * @method: The method for which we want the declarative security flags.
11721 * Return the declarative security flags for the method (only).
11723 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11724 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11727 mono_declsec_flags_from_method (MonoMethod *method)
11729 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11730 /* FIXME: No cache (for the moment) */
11731 guint32 idx = mono_method_get_index (method);
11732 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11733 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11734 return mono_declsec_get_flags (method->klass->image, idx);
11740 * Get the security actions (in the form of flags) associated with the specified class.
11742 * @klass: The class for which we want the declarative security flags.
11743 * Return the declarative security flags for the class.
11745 * Note: We cache the flags inside the MonoClass structure as this will get
11746 * called very often (at least for each method).
11749 mono_declsec_flags_from_class (MonoClass *klass)
11751 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11752 if (!klass->ext || !klass->ext->declsec_flags) {
11755 idx = mono_metadata_token_index (klass->type_token);
11756 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11757 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11758 mono_loader_lock ();
11759 mono_class_alloc_ext (klass);
11760 mono_loader_unlock ();
11761 /* we cache the flags on classes */
11762 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11764 return klass->ext->declsec_flags;
11770 * Get the security actions (in the form of flags) associated with the specified assembly.
11772 * @assembly: The assembly for which we want the declarative security flags.
11773 * Return the declarative security flags for the assembly.
11776 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11778 guint32 idx = 1; /* there is only one assembly */
11779 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11780 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11781 return mono_declsec_get_flags (assembly->image, idx);
11786 * Fill actions for the specific index (which may either be an encoded class token or
11787 * an encoded method token) from the metadata image.
11788 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11791 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11792 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11794 MonoBoolean result = FALSE;
11796 guint32 cols [MONO_DECL_SECURITY_SIZE];
11797 int index = mono_metadata_declsec_from_index (image, token);
11800 t = &image->tables [MONO_TABLE_DECLSECURITY];
11801 for (i = index; i < t->rows; i++) {
11802 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11804 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11807 /* if present only replace (class) permissions with method permissions */
11808 /* if empty accept either class or method permissions */
11809 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11810 if (!actions->demand.blob) {
11811 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11812 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11813 actions->demand.blob = (char*) (blob + 2);
11814 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11817 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11818 if (!actions->noncasdemand.blob) {
11819 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11820 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11821 actions->noncasdemand.blob = (char*) (blob + 2);
11822 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11825 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11826 if (!actions->demandchoice.blob) {
11827 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11828 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11829 actions->demandchoice.blob = (char*) (blob + 2);
11830 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11840 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11841 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11843 guint32 idx = mono_metadata_token_index (klass->type_token);
11844 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11845 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11846 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11850 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11851 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11853 guint32 idx = mono_method_get_index (method);
11854 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11855 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11856 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11860 * Collect all actions (that requires to generate code in mini) assigned for
11861 * the specified method.
11862 * Note: Don't use the content of actions if the function return FALSE.
11865 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11867 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11868 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11869 MonoBoolean result = FALSE;
11872 /* quick exit if no declarative security is present in the metadata */
11873 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11876 /* we want the original as the wrapper is "free" of the security informations */
11877 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11878 method = mono_marshal_method_from_wrapper (method);
11883 /* First we look for method-level attributes */
11884 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11885 mono_class_init (method->klass);
11886 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11888 result = mono_declsec_get_method_demands_params (method, demands,
11889 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11892 /* Here we use (or create) the class declarative cache to look for demands */
11893 flags = mono_declsec_flags_from_class (method->klass);
11894 if (flags & mask) {
11896 mono_class_init (method->klass);
11897 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11899 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11900 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11903 /* The boolean return value is used as a shortcut in case nothing needs to
11904 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11910 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11912 * Note: Don't use the content of actions if the function return FALSE.
11915 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11917 MonoBoolean result = FALSE;
11920 /* quick exit if no declarative security is present in the metadata */
11921 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11924 /* we want the original as the wrapper is "free" of the security informations */
11925 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11926 method = mono_marshal_method_from_wrapper (method);
11931 /* results are independant - zeroize both */
11932 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11933 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11935 /* First we look for method-level attributes */
11936 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11937 mono_class_init (method->klass);
11939 result = mono_declsec_get_method_demands_params (method, cmethod,
11940 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11943 /* Here we use (or create) the class declarative cache to look for demands */
11944 flags = mono_declsec_flags_from_class (method->klass);
11945 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11946 mono_class_init (method->klass);
11948 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11949 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11956 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11958 * @klass The inherited class - this is the class that provides the security check (attributes)
11960 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11962 * Note: Don't use the content of actions if the function return FALSE.
11965 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11967 MonoBoolean result = FALSE;
11970 /* quick exit if no declarative security is present in the metadata */
11971 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11974 /* Here we use (or create) the class declarative cache to look for demands */
11975 flags = mono_declsec_flags_from_class (klass);
11976 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11977 mono_class_init (klass);
11978 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11980 result |= mono_declsec_get_class_demands_params (klass, demands,
11981 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11988 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11990 * Note: Don't use the content of actions if the function return FALSE.
11993 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11995 /* quick exit if no declarative security is present in the metadata */
11996 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11999 /* we want the original as the wrapper is "free" of the security informations */
12000 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12001 method = mono_marshal_method_from_wrapper (method);
12006 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12007 mono_class_init (method->klass);
12008 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12010 return mono_declsec_get_method_demands_params (method, demands,
12011 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12018 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12020 guint32 cols [MONO_DECL_SECURITY_SIZE];
12024 int index = mono_metadata_declsec_from_index (image, token);
12028 t = &image->tables [MONO_TABLE_DECLSECURITY];
12029 for (i = index; i < t->rows; i++) {
12030 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12032 /* shortcut - index are ordered */
12033 if (token != cols [MONO_DECL_SECURITY_PARENT])
12036 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12037 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12038 entry->blob = (char*) (metadata + 2);
12039 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12048 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12050 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12051 guint32 idx = mono_method_get_index (method);
12052 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12053 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12054 return get_declsec_action (method->klass->image, idx, action, entry);
12060 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12063 guint32 flags = mono_declsec_flags_from_class (klass);
12064 if (declsec_flags_map [action] & flags) {
12065 guint32 idx = mono_metadata_token_index (klass->type_token);
12066 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12067 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12068 return get_declsec_action (klass->image, idx, action, entry);
12074 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12076 guint32 idx = 1; /* there is only one assembly */
12077 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12078 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12080 return get_declsec_action (assembly->image, idx, action, entry);
12084 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12086 MonoObject *res, *exc;
12088 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12089 static MonoMethod *method = NULL;
12091 if (!System_Reflection_Emit_TypeBuilder) {
12092 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12093 g_assert (System_Reflection_Emit_TypeBuilder);
12095 if (method == NULL) {
12096 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12101 * The result of mono_type_get_object () might be a System.MonoType but we
12102 * need a TypeBuilder so use klass->reflection_info.
12104 g_assert (klass->reflection_info);
12105 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
12107 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12109 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
12113 return *(MonoBoolean*)mono_object_unbox (res);