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 (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2572 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2573 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2578 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2581 ReflectionMethodBuilder rmb;
2584 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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 mono_g_hash_table_insert (assembly->handleref_managed, 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->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4952 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4953 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4954 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4955 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4956 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4957 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4958 image->gen_params = g_ptr_array_new ();
4960 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4961 string_heap_init (&image->sheap);
4962 mono_image_add_stream_data (&image->us, "", 1);
4963 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4964 /* import tables... */
4965 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4966 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4967 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4968 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4969 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4970 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4971 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4972 stream_data_align (&image->code);
4974 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4976 for (i=0; i < MONO_TABLE_NUM; ++i) {
4977 image->tables [i].next_idx = 1;
4978 image->tables [i].columns = table_sizes [i];
4981 image->image.assembly = (MonoAssembly*)assembly;
4982 image->run = assembly->run;
4983 image->save = assembly->save;
4984 image->pe_kind = 0x1; /* ILOnly */
4985 image->machine = 0x14c; /* I386 */
4987 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4994 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5000 mono_dynamic_image_free (MonoDynamicImage *image)
5002 MonoDynamicImage *di = image;
5007 mono_g_hash_table_destroy (di->methodspec);
5009 g_hash_table_destroy (di->typespec);
5011 g_hash_table_destroy (di->typeref);
5013 g_hash_table_destroy (di->handleref);
5014 if (di->handleref_managed)
5015 mono_g_hash_table_destroy (di->handleref_managed);
5017 mono_g_hash_table_destroy (di->tokens);
5018 if (di->generic_def_objects)
5019 mono_g_hash_table_destroy (di->generic_def_objects);
5020 if (di->blob_cache) {
5021 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5022 g_hash_table_destroy (di->blob_cache);
5024 if (di->standalonesig_cache)
5025 g_hash_table_destroy (di->standalonesig_cache);
5026 for (list = di->array_methods; list; list = list->next) {
5027 ArrayMethod *am = (ArrayMethod *)list->data;
5032 g_list_free (di->array_methods);
5033 if (di->gen_params) {
5034 for (i = 0; i < di->gen_params->len; i++) {
5035 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5036 if (entry->gparam->type.type) {
5037 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5038 g_free ((char*)mono_generic_param_info (param)->name);
5041 mono_gc_deregister_root ((char*) &entry->gparam);
5044 g_ptr_array_free (di->gen_params, TRUE);
5046 if (di->token_fixups)
5047 mono_g_hash_table_destroy (di->token_fixups);
5048 if (di->method_to_table_idx)
5049 g_hash_table_destroy (di->method_to_table_idx);
5050 if (di->field_to_table_idx)
5051 g_hash_table_destroy (di->field_to_table_idx);
5052 if (di->method_aux_hash)
5053 g_hash_table_destroy (di->method_aux_hash);
5054 g_free (di->strong_name);
5055 g_free (di->win32_res);
5057 g_free (di->public_key);
5059 /*g_print ("string heap destroy for image %p\n", di);*/
5060 mono_dynamic_stream_reset (&di->sheap);
5061 mono_dynamic_stream_reset (&di->code);
5062 mono_dynamic_stream_reset (&di->resources);
5063 mono_dynamic_stream_reset (&di->us);
5064 mono_dynamic_stream_reset (&di->blob);
5065 mono_dynamic_stream_reset (&di->tstream);
5066 mono_dynamic_stream_reset (&di->guid);
5067 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5068 g_free (di->tables [i].values);
5072 #ifndef DISABLE_REFLECTION_EMIT
5075 * mono_image_basic_init:
5076 * @assembly: an assembly builder object
5078 * Create the MonoImage that represents the assembly builder and setup some
5079 * of the helper hash table and the basic metadata streams.
5082 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5084 MonoDynamicAssembly *assembly;
5085 MonoDynamicImage *image;
5086 MonoDomain *domain = mono_object_domain (assemblyb);
5088 MONO_ARCH_SAVE_REGS;
5090 if (assemblyb->dynamic_assembly)
5094 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5096 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5099 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5101 assembly->assembly.ref_count = 1;
5102 assembly->assembly.dynamic = TRUE;
5103 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5104 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5105 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5106 if (assemblyb->culture)
5107 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5109 assembly->assembly.aname.culture = g_strdup ("");
5111 if (assemblyb->version) {
5112 char *vstr = mono_string_to_utf8 (assemblyb->version);
5113 char **version = g_strsplit (vstr, ".", 4);
5114 char **parts = version;
5115 assembly->assembly.aname.major = atoi (*parts++);
5116 assembly->assembly.aname.minor = atoi (*parts++);
5117 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5118 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5120 g_strfreev (version);
5123 assembly->assembly.aname.major = 0;
5124 assembly->assembly.aname.minor = 0;
5125 assembly->assembly.aname.build = 0;
5126 assembly->assembly.aname.revision = 0;
5129 assembly->run = assemblyb->access != 2;
5130 assembly->save = assemblyb->access != 1;
5131 assembly->domain = domain;
5133 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5134 image->initial_image = TRUE;
5135 assembly->assembly.aname.name = image->image.name;
5136 assembly->assembly.image = &image->image;
5137 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5138 /* -1 to correct for the trailing NULL byte */
5139 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5140 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5142 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5145 mono_domain_assemblies_lock (domain);
5146 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5147 mono_domain_assemblies_unlock (domain);
5149 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5151 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5153 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5156 #endif /* !DISABLE_REFLECTION_EMIT */
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5161 calc_section_size (MonoDynamicImage *assembly)
5165 /* alignment constraints */
5166 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5167 g_assert ((assembly->code.index % 4) == 0);
5168 assembly->meta_size += 3;
5169 assembly->meta_size &= ~3;
5170 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5171 g_assert ((assembly->resources.index % 4) == 0);
5173 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5174 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5177 if (assembly->win32_res) {
5178 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5180 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5181 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5185 assembly->sections [MONO_SECTION_RELOC].size = 12;
5186 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5196 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5200 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5202 ResTreeNode *t1 = (ResTreeNode*)a;
5203 ResTreeNode *t2 = (ResTreeNode*)b;
5205 return t1->id - t2->id;
5209 * resource_tree_create:
5211 * Organize the resources into a resource tree.
5213 static ResTreeNode *
5214 resource_tree_create (MonoArray *win32_resources)
5216 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5220 tree = g_new0 (ResTreeNode, 1);
5222 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5223 MonoReflectionWin32Resource *win32_res =
5224 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5228 /* FIXME: BUG: this stores managed references in unmanaged memory */
5229 lang_node = g_new0 (ResTreeNode, 1);
5230 lang_node->id = win32_res->lang_id;
5231 lang_node->win32_res = win32_res;
5233 /* Create type node if neccesary */
5235 for (l = tree->children; l; l = l->next)
5236 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5237 type_node = (ResTreeNode*)l->data;
5242 type_node = g_new0 (ResTreeNode, 1);
5243 type_node->id = win32_res->res_type;
5246 * The resource types have to be sorted otherwise
5247 * Windows Explorer can't display the version information.
5249 tree->children = g_slist_insert_sorted (tree->children,
5250 type_node, resource_tree_compare_by_id);
5253 /* Create res node if neccesary */
5255 for (l = type_node->children; l; l = l->next)
5256 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5257 res_node = (ResTreeNode*)l->data;
5262 res_node = g_new0 (ResTreeNode, 1);
5263 res_node->id = win32_res->res_id;
5264 type_node->children = g_slist_append (type_node->children, res_node);
5267 res_node->children = g_slist_append (res_node->children, lang_node);
5274 * resource_tree_encode:
5276 * Encode the resource tree into the format used in the PE file.
5279 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5282 MonoPEResourceDir dir;
5283 MonoPEResourceDirEntry dir_entry;
5284 MonoPEResourceDataEntry data_entry;
5286 guint32 res_id_entries;
5289 * For the format of the resource directory, see the article
5290 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5294 memset (&dir, 0, sizeof (dir));
5295 memset (&dir_entry, 0, sizeof (dir_entry));
5296 memset (&data_entry, 0, sizeof (data_entry));
5298 g_assert (sizeof (dir) == 16);
5299 g_assert (sizeof (dir_entry) == 8);
5300 g_assert (sizeof (data_entry) == 16);
5302 node->offset = p - begin;
5304 /* IMAGE_RESOURCE_DIRECTORY */
5305 res_id_entries = g_slist_length (node->children);
5306 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5308 memcpy (p, &dir, sizeof (dir));
5311 /* Reserve space for entries */
5313 p += sizeof (dir_entry) * res_id_entries;
5315 /* Write children */
5316 for (l = node->children; l; l = l->next) {
5317 ResTreeNode *child = (ResTreeNode*)l->data;
5319 if (child->win32_res) {
5322 child->offset = p - begin;
5324 /* IMAGE_RESOURCE_DATA_ENTRY */
5325 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5326 size = mono_array_length (child->win32_res->res_data);
5327 data_entry.rde_size = GUINT32_TO_LE (size);
5329 memcpy (p, &data_entry, sizeof (data_entry));
5330 p += sizeof (data_entry);
5332 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5335 resource_tree_encode (child, begin, p, &p);
5339 /* IMAGE_RESOURCE_ENTRY */
5340 for (l = node->children; l; l = l->next) {
5341 ResTreeNode *child = (ResTreeNode*)l->data;
5343 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5344 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5346 memcpy (entries, &dir_entry, sizeof (dir_entry));
5347 entries += sizeof (dir_entry);
5354 resource_tree_free (ResTreeNode * node)
5357 for (list = node->children; list; list = list->next)
5358 resource_tree_free ((ResTreeNode*)list->data);
5359 g_slist_free(node->children);
5364 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5369 MonoReflectionWin32Resource *win32_res;
5372 if (!assemblyb->win32_resources)
5376 * Resources are stored in a three level tree inside the PE file.
5377 * - level one contains a node for each type of resource
5378 * - level two contains a node for each resource
5379 * - level three contains a node for each instance of a resource for a
5380 * specific language.
5383 tree = resource_tree_create (assemblyb->win32_resources);
5385 /* Estimate the size of the encoded tree */
5387 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5388 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5389 size += mono_array_length (win32_res->res_data);
5391 /* Directory structure */
5392 size += mono_array_length (assemblyb->win32_resources) * 256;
5393 p = buf = g_malloc (size);
5395 resource_tree_encode (tree, p, p, &p);
5397 g_assert (p - buf <= size);
5399 assembly->win32_res = g_malloc (p - buf);
5400 assembly->win32_res_size = p - buf;
5401 memcpy (assembly->win32_res, buf, p - buf);
5404 resource_tree_free (tree);
5408 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5410 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5413 p += sizeof (MonoPEResourceDir);
5414 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5415 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5416 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5417 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5418 fixup_resource_directory (res_section, child, rva);
5420 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5421 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5424 p += sizeof (MonoPEResourceDirEntry);
5429 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5432 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5433 g_error ("WriteFile returned %d\n", GetLastError ());
5437 * mono_image_create_pefile:
5438 * @mb: a module builder object
5440 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5441 * assembly->pefile where it can be easily retrieved later in chunks.
5444 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5446 MonoMSDOSHeader *msdos;
5447 MonoDotNetHeader *header;
5448 MonoSectionTable *section;
5449 MonoCLIHeader *cli_header;
5450 guint32 size, image_size, virtual_base, text_offset;
5451 guint32 header_start, section_start, file_offset, virtual_offset;
5452 MonoDynamicImage *assembly;
5453 MonoReflectionAssemblyBuilder *assemblyb;
5454 MonoDynamicStream pefile_stream = {0};
5455 MonoDynamicStream *pefile = &pefile_stream;
5457 guint32 *rva, value;
5459 static const unsigned char msheader[] = {
5460 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5461 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5464 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5465 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5466 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5467 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5470 assemblyb = mb->assemblyb;
5472 mono_image_basic_init (assemblyb);
5473 assembly = mb->dynamic_image;
5475 assembly->pe_kind = assemblyb->pe_kind;
5476 assembly->machine = assemblyb->machine;
5477 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5478 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5480 mono_image_build_metadata (mb);
5482 if (mb->is_main && assemblyb->resources) {
5483 int len = mono_array_length (assemblyb->resources);
5484 for (i = 0; i < len; ++i)
5485 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5488 if (mb->resources) {
5489 int len = mono_array_length (mb->resources);
5490 for (i = 0; i < len; ++i)
5491 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5494 build_compressed_metadata (assembly);
5497 assembly_add_win32_resources (assembly, assemblyb);
5499 nsections = calc_section_size (assembly);
5501 /* The DOS header and stub */
5502 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5503 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5505 /* the dotnet header */
5506 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5508 /* the section tables */
5509 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5511 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5512 virtual_offset = VIRT_ALIGN;
5515 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5516 if (!assembly->sections [i].size)
5519 file_offset += FILE_ALIGN - 1;
5520 file_offset &= ~(FILE_ALIGN - 1);
5521 virtual_offset += VIRT_ALIGN - 1;
5522 virtual_offset &= ~(VIRT_ALIGN - 1);
5524 assembly->sections [i].offset = file_offset;
5525 assembly->sections [i].rva = virtual_offset;
5527 file_offset += assembly->sections [i].size;
5528 virtual_offset += assembly->sections [i].size;
5529 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5532 file_offset += FILE_ALIGN - 1;
5533 file_offset &= ~(FILE_ALIGN - 1);
5535 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5537 /* back-patch info */
5538 msdos = (MonoMSDOSHeader*)pefile->data;
5539 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5541 header = (MonoDotNetHeader*)(pefile->data + header_start);
5542 header->pesig [0] = 'P';
5543 header->pesig [1] = 'E';
5545 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5546 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5547 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5548 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5549 if (assemblyb->pekind == 1) {
5551 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5554 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5557 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5559 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5560 header->pe.pe_major = 6;
5561 header->pe.pe_minor = 0;
5562 size = assembly->sections [MONO_SECTION_TEXT].size;
5563 size += FILE_ALIGN - 1;
5564 size &= ~(FILE_ALIGN - 1);
5565 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5566 size = assembly->sections [MONO_SECTION_RSRC].size;
5567 size += FILE_ALIGN - 1;
5568 size &= ~(FILE_ALIGN - 1);
5569 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5570 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5571 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5572 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5573 /* pe_rva_entry_point always at the beginning of the text section */
5574 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5576 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5577 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5578 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5579 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5580 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5581 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5582 size = section_start;
5583 size += FILE_ALIGN - 1;
5584 size &= ~(FILE_ALIGN - 1);
5585 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5587 size += VIRT_ALIGN - 1;
5588 size &= ~(VIRT_ALIGN - 1);
5589 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5592 // Translate the PEFileKind value to the value expected by the Windows loader
5598 // PEFileKinds.Dll == 1
5599 // PEFileKinds.ConsoleApplication == 2
5600 // PEFileKinds.WindowApplication == 3
5603 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5604 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5606 if (assemblyb->pekind == 3)
5611 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5613 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5614 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5615 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5616 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5617 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5618 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5620 /* fill data directory entries */
5622 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5623 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5625 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5626 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5628 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5629 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5630 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5631 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5632 /* patch entrypoint name */
5633 if (assemblyb->pekind == 1)
5634 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5636 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5637 /* patch imported function RVA name */
5638 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5639 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5641 /* the import table */
5642 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5643 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5644 /* patch imported dll RVA name and other entries in the dir */
5645 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5646 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5647 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5648 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5649 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5650 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5652 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5653 value = (assembly->text_rva + assembly->imp_names_offset);
5654 *p++ = (value) & 0xff;
5655 *p++ = (value >> 8) & (0xff);
5656 *p++ = (value >> 16) & (0xff);
5657 *p++ = (value >> 24) & (0xff);
5659 /* the CLI header info */
5660 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5661 cli_header->ch_size = GUINT32_FROM_LE (72);
5662 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5663 if (mono_framework_version () > 1)
5664 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5666 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5667 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5668 if (assemblyb->entry_point) {
5669 guint32 table_idx = 0;
5670 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5671 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5672 table_idx = methodb->table_idx;
5674 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5676 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5678 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5680 /* The embedded managed resources */
5681 text_offset = assembly->text_rva + assembly->code.index;
5682 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5683 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5684 text_offset += assembly->resources.index;
5685 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5686 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5687 text_offset += assembly->meta_size;
5688 if (assembly->strong_name_size) {
5689 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5690 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5691 text_offset += assembly->strong_name_size;
5694 /* write the section tables and section content */
5695 section = (MonoSectionTable*)(pefile->data + section_start);
5696 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5697 static const char section_names [][7] = {
5698 ".text", ".rsrc", ".reloc"
5700 if (!assembly->sections [i].size)
5702 strcpy (section->st_name, section_names [i]);
5703 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5704 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5705 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5706 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5707 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5708 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5709 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5713 checked_write_file (file, pefile->data, pefile->index);
5715 mono_dynamic_stream_reset (pefile);
5717 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5718 if (!assembly->sections [i].size)
5721 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5722 g_error ("SetFilePointer returned %d\n", GetLastError ());
5725 case MONO_SECTION_TEXT:
5726 /* patch entry point */
5727 p = (guchar*)(assembly->code.data + 2);
5728 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5729 *p++ = (value) & 0xff;
5730 *p++ = (value >> 8) & 0xff;
5731 *p++ = (value >> 16) & 0xff;
5732 *p++ = (value >> 24) & 0xff;
5734 checked_write_file (file, assembly->code.data, assembly->code.index);
5735 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5736 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5737 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5740 g_free (assembly->image.raw_metadata);
5742 case MONO_SECTION_RELOC: {
5746 guint16 type_and_offset;
5750 g_assert (sizeof (reloc) == 12);
5752 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5753 reloc.block_size = GUINT32_FROM_LE (12);
5756 * the entrypoint is always at the start of the text section
5757 * 3 is IMAGE_REL_BASED_HIGHLOW
5758 * 2 is patch_size_rva - text_rva
5760 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5763 checked_write_file (file, &reloc, sizeof (reloc));
5767 case MONO_SECTION_RSRC:
5768 if (assembly->win32_res) {
5770 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5771 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5772 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5776 g_assert_not_reached ();
5780 /* check that the file is properly padded */
5781 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5782 g_error ("SetFilePointer returned %d\n", GetLastError ());
5783 if (! SetEndOfFile (file))
5784 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5786 mono_dynamic_stream_reset (&assembly->code);
5787 mono_dynamic_stream_reset (&assembly->us);
5788 mono_dynamic_stream_reset (&assembly->blob);
5789 mono_dynamic_stream_reset (&assembly->guid);
5790 mono_dynamic_stream_reset (&assembly->sheap);
5792 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5793 g_hash_table_destroy (assembly->blob_cache);
5794 assembly->blob_cache = NULL;
5797 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5800 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5802 g_assert_not_reached ();
5805 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5807 #ifndef DISABLE_REFLECTION_EMIT
5809 MonoReflectionModule *
5810 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5814 MonoImageOpenStatus status;
5815 MonoDynamicAssembly *assembly;
5816 guint32 module_count;
5817 MonoImage **new_modules;
5818 gboolean *new_modules_loaded;
5820 name = mono_string_to_utf8 (fileName);
5822 image = mono_image_open (name, &status);
5825 if (status == MONO_IMAGE_ERROR_ERRNO)
5826 exc = mono_get_exception_file_not_found (fileName);
5828 exc = mono_get_exception_bad_image_format (name);
5830 mono_raise_exception (exc);
5835 assembly = ab->dynamic_assembly;
5836 image->assembly = (MonoAssembly*)assembly;
5838 module_count = image->assembly->image->module_count;
5839 new_modules = g_new0 (MonoImage *, module_count + 1);
5840 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5842 if (image->assembly->image->modules)
5843 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5844 if (image->assembly->image->modules_loaded)
5845 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5846 new_modules [module_count] = image;
5847 new_modules_loaded [module_count] = TRUE;
5848 mono_image_addref (image);
5850 g_free (image->assembly->image->modules);
5851 image->assembly->image->modules = new_modules;
5852 image->assembly->image->modules_loaded = new_modules_loaded;
5853 image->assembly->image->module_count ++;
5855 mono_assembly_load_references (image, &status);
5857 mono_image_close (image);
5858 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5861 return mono_module_get_object (mono_domain_get (), image);
5864 #endif /* DISABLE_REFLECTION_EMIT */
5867 * We need to return always the same object for MethodInfo, FieldInfo etc..
5868 * but we need to consider the reflected type.
5869 * type uses a different hash, since it uses custom hash/equal functions.
5874 MonoClass *refclass;
5878 reflected_equal (gconstpointer a, gconstpointer b) {
5879 const ReflectedEntry *ea = a;
5880 const ReflectedEntry *eb = b;
5882 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5886 reflected_hash (gconstpointer a) {
5887 const ReflectedEntry *ea = a;
5888 return mono_aligned_addr_hash (ea->item);
5891 #define CHECK_OBJECT(t,p,k) \
5897 mono_domain_lock (domain); \
5898 if (!domain->refobject_hash) \
5899 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5900 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5901 mono_domain_unlock (domain); \
5904 mono_domain_unlock (domain); \
5907 #ifdef HAVE_BOEHM_GC
5908 /* ReflectedEntry doesn't need to be GC tracked */
5909 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5910 #define FREE_REFENTRY(entry) g_free ((entry))
5911 #define REFENTRY_REQUIRES_CLEANUP
5913 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5915 #define FREE_REFENTRY(entry)
5918 #define CACHE_OBJECT(t,p,o,k) \
5921 ReflectedEntry pe; \
5923 pe.refclass = (k); \
5924 mono_domain_lock (domain); \
5925 if (!domain->refobject_hash) \
5926 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5927 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5929 ReflectedEntry *e = ALLOC_REFENTRY; \
5931 e->refclass = (k); \
5932 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5935 mono_domain_unlock (domain); \
5940 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5942 mono_domain_lock (domain);
5943 if (domain->refobject_hash) {
5945 gpointer orig_pe, orig_value;
5948 pe.refclass = klass;
5949 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5950 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5951 FREE_REFENTRY (orig_pe);
5954 mono_domain_unlock (domain);
5957 #ifdef REFENTRY_REQUIRES_CLEANUP
5959 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5961 FREE_REFENTRY (key);
5966 mono_reflection_cleanup_domain (MonoDomain *domain)
5968 if (domain->refobject_hash) {
5969 /*let's avoid scanning the whole hashtable if not needed*/
5970 #ifdef REFENTRY_REQUIRES_CLEANUP
5971 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5973 mono_g_hash_table_destroy (domain->refobject_hash);
5974 domain->refobject_hash = NULL;
5978 #ifndef DISABLE_REFLECTION_EMIT
5980 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5982 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5986 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5988 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5992 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5994 MonoDynamicImage *image = moduleb->dynamic_image;
5995 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5999 MonoImage **new_modules;
6001 char *name, *fqname;
6003 * FIXME: we already created an image in mono_image_basic_init (), but
6004 * we don't know which module it belongs to, since that is only
6005 * determined at assembly save time.
6007 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6008 name = mono_string_to_utf8 (ab->name);
6009 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6010 if (!mono_error_ok (&error)) {
6012 mono_error_raise_exception (&error);
6014 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6016 moduleb->module.image = &image->image;
6017 moduleb->dynamic_image = image;
6018 register_module (mono_object_domain (moduleb), moduleb, image);
6020 /* register the module with the assembly */
6021 ass = ab->dynamic_assembly->assembly.image;
6022 module_count = ass->module_count;
6023 new_modules = g_new0 (MonoImage *, module_count + 1);
6026 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6027 new_modules [module_count] = &image->image;
6028 mono_image_addref (&image->image);
6030 g_free (ass->modules);
6031 ass->modules = new_modules;
6032 ass->module_count ++;
6037 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6039 MonoDynamicImage *image = moduleb->dynamic_image;
6041 g_assert (type->type);
6042 image->wrappers_type = mono_class_from_mono_type (type->type);
6048 * mono_assembly_get_object:
6049 * @domain: an app domain
6050 * @assembly: an assembly
6052 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6054 MonoReflectionAssembly*
6055 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6057 static MonoClass *System_Reflection_Assembly;
6058 MonoReflectionAssembly *res;
6060 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6061 if (!System_Reflection_Assembly)
6062 System_Reflection_Assembly = mono_class_from_name (
6063 mono_defaults.corlib, "System.Reflection", "Assembly");
6064 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
6065 res->assembly = assembly;
6067 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6072 MonoReflectionModule*
6073 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6075 static MonoClass *System_Reflection_Module;
6076 MonoReflectionModule *res;
6079 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6080 if (!System_Reflection_Module)
6081 System_Reflection_Module = mono_class_from_name (
6082 mono_defaults.corlib, "System.Reflection", "Module");
6083 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6086 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6088 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6089 basename = g_path_get_basename (image->name);
6090 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6091 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6095 if (image->assembly->image == image) {
6096 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6100 if (image->assembly->image->modules) {
6101 for (i = 0; i < image->assembly->image->module_count; i++) {
6102 if (image->assembly->image->modules [i] == image)
6103 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6105 g_assert (res->token);
6109 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6112 MonoReflectionModule*
6113 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6115 static MonoClass *System_Reflection_Module;
6116 MonoReflectionModule *res;
6117 MonoTableInfo *table;
6118 guint32 cols [MONO_FILE_SIZE];
6120 guint32 i, name_idx;
6123 if (!System_Reflection_Module)
6124 System_Reflection_Module = mono_class_from_name (
6125 mono_defaults.corlib, "System.Reflection", "Module");
6126 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6128 table = &image->tables [MONO_TABLE_FILE];
6129 g_assert (table_index < table->rows);
6130 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6133 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6134 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6136 /* Check whenever the row has a corresponding row in the moduleref table */
6137 table = &image->tables [MONO_TABLE_MODULEREF];
6138 for (i = 0; i < table->rows; ++i) {
6139 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6140 val = mono_metadata_string_heap (image, name_idx);
6141 if (strcmp (val, name) == 0)
6142 res->image = image->modules [i];
6145 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6146 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6147 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6148 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6149 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6155 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6157 if ((t1->type != t2->type) ||
6158 (t1->byref != t2->byref))
6162 case MONO_TYPE_VOID:
6163 case MONO_TYPE_BOOLEAN:
6164 case MONO_TYPE_CHAR:
6175 case MONO_TYPE_STRING:
6178 case MONO_TYPE_OBJECT:
6179 case MONO_TYPE_TYPEDBYREF:
6181 case MONO_TYPE_VALUETYPE:
6182 case MONO_TYPE_CLASS:
6183 case MONO_TYPE_SZARRAY:
6184 return t1->data.klass == t2->data.klass;
6186 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6187 case MONO_TYPE_ARRAY:
6188 if (t1->data.array->rank != t2->data.array->rank)
6190 return t1->data.array->eklass == t2->data.array->eklass;
6191 case MONO_TYPE_GENERICINST: {
6193 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6194 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6195 if (i1->type_argc != i2->type_argc)
6197 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6198 &t2->data.generic_class->container_class->byval_arg))
6200 /* FIXME: we should probably just compare the instance pointers directly. */
6201 for (i = 0; i < i1->type_argc; ++i) {
6202 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6208 case MONO_TYPE_MVAR:
6209 return t1->data.generic_param == t2->data.generic_param;
6211 g_error ("implement type compare for %0x!", t1->type);
6219 mymono_metadata_type_hash (MonoType *t1)
6225 hash |= t1->byref << 6; /* do not collide with t1->type values */
6227 case MONO_TYPE_VALUETYPE:
6228 case MONO_TYPE_CLASS:
6229 case MONO_TYPE_SZARRAY:
6230 /* check if the distribution is good enough */
6231 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6233 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6234 case MONO_TYPE_GENERICINST: {
6236 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6237 hash += g_str_hash (t1->data.generic_class->container_class->name);
6239 for (i = 0; i < inst->type_argc; ++i) {
6240 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6249 static MonoReflectionGenericClass*
6250 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6252 static MonoClass *System_Reflection_MonoGenericClass;
6253 MonoReflectionGenericClass *res;
6254 MonoClass *klass, *gklass;
6255 MonoGenericInst *ginst;
6256 MonoArray *type_args;
6259 g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6261 if (!System_Reflection_MonoGenericClass) {
6262 System_Reflection_MonoGenericClass = mono_class_from_name (
6263 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6264 g_assert (System_Reflection_MonoGenericClass);
6267 klass = mono_class_from_mono_type (geninst);
6268 gklass = klass->generic_class->container_class;
6270 mono_class_init (klass);
6273 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6275 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6278 res->type.type = geninst;
6279 g_assert (gklass->reflection_info);
6280 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6281 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6283 ginst = klass->generic_class->context.class_inst;
6284 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6285 for (i = 0; i < ginst->type_argc; ++i)
6286 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6287 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6293 verify_safe_for_managed_space (MonoType *type)
6295 switch (type->type) {
6297 case MONO_TYPE_ARRAY:
6298 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6300 return verify_safe_for_managed_space (type->data.type);
6301 case MONO_TYPE_SZARRAY:
6302 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6303 case MONO_TYPE_GENERICINST: {
6304 MonoGenericInst *inst = type->data.generic_class->inst;
6308 for (i = 0; i < inst->type_argc; ++i)
6309 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6315 case MONO_TYPE_MVAR:
6322 * mono_type_get_object:
6323 * @domain: an app domain
6326 * Return an System.MonoType object representing the type @type.
6329 mono_type_get_object (MonoDomain *domain, MonoType *type)
6331 MonoReflectionType *res;
6332 MonoClass *klass = mono_class_from_mono_type (type);
6334 /*we must avoid using @type as it might have come
6335 * from a mono_metadata_type_dup and the caller
6336 * expects that is can be freed.
6337 * Using the right type from
6339 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6341 /* void is very common */
6342 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6343 return (MonoReflectionType*)domain->typeof_void;
6346 * If the vtable of the given class was already created, we can use
6347 * the MonoType from there and avoid all locking and hash table lookups.
6349 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6350 * that the resulting object is different.
6352 if (type == &klass->byval_arg && !klass->image->dynamic) {
6353 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6354 if (vtable && vtable->type)
6355 return vtable->type;
6358 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6359 mono_domain_lock (domain);
6360 if (!domain->type_hash)
6361 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6362 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6363 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6364 mono_domain_unlock (domain);
6365 mono_loader_unlock ();
6368 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6369 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6370 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6371 mono_g_hash_table_insert (domain->type_hash, type, res);
6372 mono_domain_unlock (domain);
6373 mono_loader_unlock ();
6377 if (!verify_safe_for_managed_space (type)) {
6378 mono_domain_unlock (domain);
6379 mono_loader_unlock ();
6380 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6383 if (klass->reflection_info && !klass->wastypebuilder) {
6384 gboolean is_type_done = TRUE;
6385 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6386 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6387 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6389 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6390 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6392 if (gparam->owner && gparam->owner->is_method) {
6393 MonoMethod *method = gparam->owner->owner.method;
6394 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6395 is_type_done = FALSE;
6396 } else if (gparam->owner && !gparam->owner->is_method) {
6397 MonoClass *klass = gparam->owner->owner.klass;
6398 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6399 is_type_done = FALSE;
6403 /* g_assert_not_reached (); */
6404 /* should this be considered an error condition? */
6405 if (is_type_done && !type->byref) {
6406 mono_domain_unlock (domain);
6407 mono_loader_unlock ();
6408 return klass->reflection_info;
6411 // FIXME: Get rid of this, do it in the icalls for Type
6412 mono_class_init (klass);
6414 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6416 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6419 mono_g_hash_table_insert (domain->type_hash, type, res);
6421 if (type->type == MONO_TYPE_VOID)
6422 domain->typeof_void = (MonoObject*)res;
6424 mono_domain_unlock (domain);
6425 mono_loader_unlock ();
6430 * mono_method_get_object:
6431 * @domain: an app domain
6433 * @refclass: the reflected type (can be NULL)
6435 * Return an System.Reflection.MonoMethod object representing the method @method.
6437 MonoReflectionMethod*
6438 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6441 * We use the same C representation for methods and constructors, but the type
6442 * name in C# is different.
6444 static MonoClass *System_Reflection_MonoMethod = NULL;
6445 static MonoClass *System_Reflection_MonoCMethod = NULL;
6446 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6447 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6449 MonoReflectionMethod *ret;
6451 if (method->is_inflated) {
6452 MonoReflectionGenericMethod *gret;
6454 refclass = method->klass;
6455 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6456 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6457 if (!System_Reflection_MonoGenericCMethod)
6458 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6459 klass = System_Reflection_MonoGenericCMethod;
6461 if (!System_Reflection_MonoGenericMethod)
6462 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6463 klass = System_Reflection_MonoGenericMethod;
6465 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6466 gret->method.method = method;
6467 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6468 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6469 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6473 refclass = method->klass;
6475 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6476 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6477 if (!System_Reflection_MonoCMethod)
6478 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6479 klass = System_Reflection_MonoCMethod;
6482 if (!System_Reflection_MonoMethod)
6483 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6484 klass = System_Reflection_MonoMethod;
6486 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6487 ret->method = method;
6488 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6489 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6493 * mono_method_clear_object:
6495 * Clear the cached reflection objects for the dynamic method METHOD.
6498 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6501 g_assert (method->dynamic);
6503 klass = method->klass;
6505 clear_cached_object (domain, method, klass);
6506 klass = klass->parent;
6508 /* Added by mono_param_get_objects () */
6509 clear_cached_object (domain, &(method->signature), NULL);
6510 klass = method->klass;
6512 clear_cached_object (domain, &(method->signature), klass);
6513 klass = klass->parent;
6518 * mono_field_get_object:
6519 * @domain: an app domain
6523 * Return an System.Reflection.MonoField object representing the field @field
6526 MonoReflectionField*
6527 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6529 MonoReflectionField *res;
6530 static MonoClass *monofield_klass;
6532 CHECK_OBJECT (MonoReflectionField *, field, klass);
6533 if (!monofield_klass)
6534 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6535 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6538 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6539 if (is_field_on_inst (field))
6540 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6542 res->attrs = field->type->attrs;
6543 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6544 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6548 * mono_property_get_object:
6549 * @domain: an app domain
6551 * @property: a property
6553 * Return an System.Reflection.MonoProperty object representing the property @property
6556 MonoReflectionProperty*
6557 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6559 MonoReflectionProperty *res;
6560 static MonoClass *monoproperty_klass;
6562 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6563 if (!monoproperty_klass)
6564 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6565 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6567 res->property = property;
6568 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6572 * mono_event_get_object:
6573 * @domain: an app domain
6577 * Return an System.Reflection.MonoEvent object representing the event @event
6580 MonoReflectionEvent*
6581 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6583 MonoReflectionEvent *res;
6584 MonoReflectionMonoEvent *mono_event;
6585 static MonoClass *monoevent_klass;
6587 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6588 if (!monoevent_klass)
6589 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6590 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6591 mono_event->klass = klass;
6592 mono_event->event = event;
6593 res = (MonoReflectionEvent*)mono_event;
6594 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6598 * mono_get_reflection_missing_object:
6599 * @domain: Domain where the object lives
6601 * Returns the System.Reflection.Missing.Value singleton object
6602 * (of type System.Reflection.Missing).
6604 * Used as the value for ParameterInfo.DefaultValue when Optional
6608 mono_get_reflection_missing_object (MonoDomain *domain)
6611 static MonoClassField *missing_value_field = NULL;
6613 if (!missing_value_field) {
6614 MonoClass *missing_klass;
6615 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6616 mono_class_init (missing_klass);
6617 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6618 g_assert (missing_value_field);
6620 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6626 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6629 *dbnull = mono_get_dbnull_object (domain);
6634 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6636 if (!*reflection_missing)
6637 *reflection_missing = mono_get_reflection_missing_object (domain);
6638 return *reflection_missing;
6642 * mono_param_get_objects:
6643 * @domain: an app domain
6646 * Return an System.Reflection.ParameterInfo array object representing the parameters
6647 * in the method @method.
6650 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6652 static MonoClass *System_Reflection_ParameterInfo;
6653 static MonoClass *System_Reflection_ParameterInfo_array;
6654 MonoArray *res = NULL;
6655 MonoReflectionMethod *member = NULL;
6656 MonoReflectionParameter *param = NULL;
6657 char **names, **blobs = NULL;
6658 guint32 *types = NULL;
6659 MonoType *type = NULL;
6660 MonoObject *dbnull = NULL;
6661 MonoObject *missing = NULL;
6662 MonoMarshalSpec **mspecs;
6663 MonoMethodSignature *sig;
6664 MonoVTable *pinfo_vtable;
6667 if (!System_Reflection_ParameterInfo_array) {
6670 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6671 mono_memory_barrier ();
6672 System_Reflection_ParameterInfo = klass;
6674 klass = mono_array_class_get (klass, 1);
6675 mono_memory_barrier ();
6676 System_Reflection_ParameterInfo_array = klass;
6679 if (!mono_method_signature (method)->param_count)
6680 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6682 /* Note: the cache is based on the address of the signature into the method
6683 * since we already cache MethodInfos with the method as keys.
6685 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6687 sig = mono_method_signature (method);
6688 member = mono_method_get_object (domain, method, refclass);
6689 names = g_new (char *, sig->param_count);
6690 mono_method_get_param_names (method, (const char **) names);
6692 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6693 mono_method_get_marshal_info (method, mspecs);
6695 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6696 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6697 for (i = 0; i < sig->param_count; ++i) {
6698 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6699 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6700 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6701 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6702 param->PositionImpl = i;
6703 param->AttrsImpl = sig->params [i]->attrs;
6705 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6706 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6707 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6709 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6713 blobs = g_new0 (char *, sig->param_count);
6714 types = g_new0 (guint32, sig->param_count);
6715 get_default_param_value_blobs (method, blobs, types);
6718 /* Build MonoType for the type from the Constant Table */
6720 type = g_new0 (MonoType, 1);
6721 type->type = types [i];
6722 type->data.klass = NULL;
6723 if (types [i] == MONO_TYPE_CLASS)
6724 type->data.klass = mono_defaults.object_class;
6725 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6726 /* For enums, types [i] contains the base type */
6728 type->type = MONO_TYPE_VALUETYPE;
6729 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6731 type->data.klass = mono_class_from_mono_type (type);
6733 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6735 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6736 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6737 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6738 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6740 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6746 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6748 mono_array_setref (res, i, param);
6755 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6757 mono_metadata_free_marshal_spec (mspecs [i]);
6760 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6764 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6766 return mono_param_get_objects_internal (domain, method, NULL);
6770 * mono_method_body_get_object:
6771 * @domain: an app domain
6774 * Return an System.Reflection.MethodBody object representing the method @method.
6776 MonoReflectionMethodBody*
6777 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6779 static MonoClass *System_Reflection_MethodBody = NULL;
6780 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6781 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6782 MonoReflectionMethodBody *ret;
6783 MonoMethodNormal *mn;
6784 MonoMethodHeader *header;
6785 guint32 method_rva, local_var_sig_token;
6787 unsigned char format, flags;
6790 if (!System_Reflection_MethodBody)
6791 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6792 if (!System_Reflection_LocalVariableInfo)
6793 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6794 if (!System_Reflection_ExceptionHandlingClause)
6795 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6797 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6799 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6800 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6801 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6802 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6804 mn = (MonoMethodNormal *)method;
6805 header = mono_method_get_header (method);
6807 /* Obtain local vars signature token */
6808 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6809 ptr = mono_image_rva_map (method->klass->image, method_rva);
6810 flags = *(const unsigned char *) ptr;
6811 format = flags & METHOD_HEADER_FORMAT_MASK;
6813 case METHOD_HEADER_TINY_FORMAT:
6814 local_var_sig_token = 0;
6816 case METHOD_HEADER_FAT_FORMAT:
6820 local_var_sig_token = read32 (ptr);
6823 g_assert_not_reached ();
6826 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6828 ret->init_locals = header->init_locals;
6829 ret->max_stack = header->max_stack;
6830 ret->local_var_sig_token = local_var_sig_token;
6831 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6832 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6835 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6836 for (i = 0; i < header->num_locals; ++i) {
6837 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6838 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6839 info->is_pinned = header->locals [i]->pinned;
6840 info->local_index = i;
6841 mono_array_setref (ret->locals, i, info);
6845 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6846 for (i = 0; i < header->num_clauses; ++i) {
6847 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6848 MonoExceptionClause *clause = &header->clauses [i];
6850 info->flags = clause->flags;
6851 info->try_offset = clause->try_offset;
6852 info->try_length = clause->try_len;
6853 info->handler_offset = clause->handler_offset;
6854 info->handler_length = clause->handler_len;
6855 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6856 info->filter_offset = clause->data.filter_offset;
6857 else if (clause->data.catch_class)
6858 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6860 mono_array_setref (ret->clauses, i, info);
6863 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6868 * mono_get_dbnull_object:
6869 * @domain: Domain where the object lives
6871 * Returns the System.DBNull.Value singleton object
6873 * Used as the value for ParameterInfo.DefaultValue
6876 mono_get_dbnull_object (MonoDomain *domain)
6879 static MonoClassField *dbnull_value_field = NULL;
6881 if (!dbnull_value_field) {
6882 MonoClass *dbnull_klass;
6883 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6884 mono_class_init (dbnull_klass);
6885 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6886 g_assert (dbnull_value_field);
6888 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6894 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6896 guint32 param_index, i, lastp, crow = 0;
6897 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6900 MonoClass *klass = method->klass;
6901 MonoImage *image = klass->image;
6902 MonoMethodSignature *methodsig = mono_method_signature (method);
6904 MonoTableInfo *constt;
6905 MonoTableInfo *methodt;
6906 MonoTableInfo *paramt;
6908 if (!methodsig->param_count)
6911 mono_class_init (klass);
6913 if (klass->image->dynamic) {
6914 MonoReflectionMethodAux *aux;
6915 if (method->is_inflated)
6916 method = ((MonoMethodInflated*)method)->declaring;
6917 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6918 if (aux && aux->param_defaults) {
6919 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6920 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6925 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6926 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6927 constt = &image->tables [MONO_TABLE_CONSTANT];
6929 idx = mono_method_get_index (method) - 1;
6930 g_assert (idx != -1);
6932 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6933 if (idx + 1 < methodt->rows)
6934 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6936 lastp = paramt->rows + 1;
6938 for (i = param_index; i < lastp; ++i) {
6941 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6942 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6944 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6947 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6952 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6953 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6954 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6961 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6966 MonoType *basetype = type;
6971 klass = mono_class_from_mono_type (type);
6972 if (klass->valuetype) {
6973 object = mono_object_new (domain, klass);
6974 retval = ((gchar *) object + sizeof (MonoObject));
6975 if (klass->enumtype)
6976 basetype = mono_class_enum_basetype (klass);
6981 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6988 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6992 memset (assembly, 0, sizeof (MonoAssemblyName));
6994 assembly->culture = "";
6995 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6997 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7000 while (g_ascii_isspace (*p) || *p == ',') {
7009 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7011 assembly->major = strtoul (p, &s, 10);
7012 if (s == p || *s != '.')
7015 assembly->minor = strtoul (p, &s, 10);
7016 if (s == p || *s != '.')
7019 assembly->build = strtoul (p, &s, 10);
7020 if (s == p || *s != '.')
7023 assembly->revision = strtoul (p, &s, 10);
7027 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7029 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7030 assembly->culture = "";
7033 assembly->culture = p;
7034 while (*p && *p != ',') {
7038 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7040 if (strncmp (p, "null", 4) == 0) {
7045 while (*p && *p != ',') {
7048 len = (p - start + 1);
7049 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7050 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7051 g_strlcpy ((char*)assembly->public_key_token, start, len);
7054 while (*p && *p != ',')
7058 while (g_ascii_isspace (*p) || *p == ',') {
7072 * mono_reflection_parse_type:
7075 * Parse a type name as accepted by the GetType () method and output the info
7076 * extracted in the info structure.
7077 * the name param will be mangled, so, make a copy before passing it to this function.
7078 * The fields in info will be valid until the memory pointed to by name is valid.
7080 * See also mono_type_get_name () below.
7082 * Returns: 0 on parse error.
7085 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7086 MonoTypeNameParse *info)
7088 char *start, *p, *w, *temp, *last_point, *startn;
7089 int in_modifiers = 0;
7090 int isbyref = 0, rank, arity = 0, i;
7092 start = p = w = name;
7094 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7095 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7096 info->name = info->name_space = NULL;
7097 info->nested = NULL;
7098 info->modifiers = NULL;
7099 info->type_arguments = NULL;
7101 /* last_point separates the namespace from the name */
7104 while (*p == ' ') p++, start++, w++, name++;
7109 *p = 0; /* NULL terminate the name */
7111 info->nested = g_list_append (info->nested, startn);
7112 /* we have parsed the nesting namespace + name */
7116 info->name_space = start;
7118 info->name = last_point + 1;
7120 info->name_space = (char *)"";
7139 i = strtol (p, &temp, 10);
7156 info->name_space = start;
7158 info->name = last_point + 1;
7160 info->name_space = (char *)"";
7167 if (isbyref) /* only one level allowed by the spec */
7170 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7174 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7180 info->type_arguments = g_ptr_array_new ();
7181 for (i = 0; i < arity; i++) {
7182 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7183 gboolean fqname = FALSE;
7185 g_ptr_array_add (info->type_arguments, subinfo);
7192 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7203 while (*p && (*p != ']'))
7211 if (g_ascii_isspace (*aname)) {
7218 !assembly_name_to_aname (&subinfo->assembly, aname))
7222 if (i + 1 < arity) {
7242 else if (*p == '*') /* '*' means unknown lower bound */
7243 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7250 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7261 if (g_ascii_isspace (*p)) {
7268 return 0; /* missing assembly name */
7269 if (!assembly_name_to_aname (&info->assembly, p))
7275 if (info->assembly.name)
7278 // *w = 0; /* terminate class name */
7280 if (!info->name || !*info->name)
7284 /* add other consistency checks */
7289 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7291 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7295 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7297 gboolean type_resolve = FALSE;
7299 MonoImage *rootimage = image;
7301 if (info->assembly.name) {
7302 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7303 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7305 * This could happen in the AOT compiler case when the search hook is not
7308 assembly = image->assembly;
7310 /* then we must load the assembly ourselve - see #60439 */
7311 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7315 image = assembly->image;
7316 } else if (!image) {
7317 image = mono_defaults.corlib;
7320 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7321 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7322 image = mono_defaults.corlib;
7323 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7330 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7335 gboolean bounded = FALSE;
7338 image = mono_defaults.corlib;
7341 klass = mono_class_from_name_case (image, info->name_space, info->name);
7343 klass = mono_class_from_name (image, info->name_space, info->name);
7346 for (mod = info->nested; mod; mod = mod->next) {
7347 gpointer iter = NULL;
7351 mono_class_init (parent);
7353 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7355 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7358 if (strcmp (klass->name, mod->data) == 0)
7367 mono_class_init (klass);
7369 if (info->type_arguments) {
7370 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7371 MonoReflectionType *the_type;
7375 for (i = 0; i < info->type_arguments->len; i++) {
7376 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7378 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7379 if (!type_args [i]) {
7385 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7387 instance = mono_reflection_bind_generic_parameters (
7388 the_type, info->type_arguments->len, type_args);
7394 klass = mono_class_from_mono_type (instance);
7397 for (mod = info->modifiers; mod; mod = mod->next) {
7398 modval = GPOINTER_TO_UINT (mod->data);
7399 if (!modval) { /* byref: must be last modifier */
7400 return &klass->this_arg;
7401 } else if (modval == -1) {
7402 klass = mono_ptr_class_get (&klass->byval_arg);
7403 } else if (modval == -2) {
7405 } else { /* array rank */
7406 klass = mono_bounded_array_class_get (klass, modval, bounded);
7408 mono_class_init (klass);
7411 return &klass->byval_arg;
7415 * mono_reflection_get_type:
7416 * @image: a metadata context
7417 * @info: type description structure
7418 * @ignorecase: flag for case-insensitive string compares
7419 * @type_resolve: whenever type resolve was already tried
7421 * Build a MonoType from the type description in @info.
7426 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7427 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7431 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7433 MonoReflectionAssemblyBuilder *abuilder;
7437 g_assert (assembly->dynamic);
7438 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7440 /* Enumerate all modules */
7443 if (abuilder->modules) {
7444 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7445 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7446 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7452 if (!type && abuilder->loaded_modules) {
7453 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7454 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7455 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7465 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7468 MonoReflectionAssembly *assembly;
7472 if (image && image->dynamic)
7473 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7475 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7478 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7485 *type_resolve = TRUE;
7488 /* Reconstruct the type name */
7489 fullName = g_string_new ("");
7490 if (info->name_space && (info->name_space [0] != '\0'))
7491 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7493 g_string_printf (fullName, "%s", info->name);
7494 for (mod = info->nested; mod; mod = mod->next)
7495 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7497 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7499 if (assembly->assembly->dynamic)
7500 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7502 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7505 g_string_free (fullName, TRUE);
7510 mono_reflection_free_type_info (MonoTypeNameParse *info)
7512 g_list_free (info->modifiers);
7513 g_list_free (info->nested);
7515 if (info->type_arguments) {
7518 for (i = 0; i < info->type_arguments->len; i++) {
7519 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7521 mono_reflection_free_type_info (subinfo);
7522 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7526 g_ptr_array_free (info->type_arguments, TRUE);
7531 * mono_reflection_type_from_name:
7533 * @image: a metadata context (can be NULL).
7535 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7536 * it defaults to get the type from @image or, if @image is NULL or loading
7537 * from it fails, uses corlib.
7541 mono_reflection_type_from_name (char *name, MonoImage *image)
7543 MonoType *type = NULL;
7544 MonoTypeNameParse info;
7547 /* Make a copy since parse_type modifies its argument */
7548 tmp = g_strdup (name);
7550 /*g_print ("requested type %s\n", str);*/
7551 if (mono_reflection_parse_type (tmp, &info)) {
7552 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7556 mono_reflection_free_type_info (&info);
7561 * mono_reflection_get_token:
7563 * Return the metadata token of OBJ which should be an object
7564 * representing a metadata element.
7567 mono_reflection_get_token (MonoObject *obj)
7572 klass = obj->vtable->klass;
7574 if (strcmp (klass->name, "MethodBuilder") == 0) {
7575 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7577 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7578 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7579 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7581 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7582 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7583 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7585 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7586 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7587 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7589 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7590 } else if (strcmp (klass->name, "MonoType") == 0) {
7591 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7592 token = mono_class_from_mono_type (type)->type_token;
7593 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7594 strcmp (klass->name, "MonoMethod") == 0 ||
7595 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7596 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7597 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7598 if (m->method->is_inflated) {
7599 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7600 return inflated->declaring->token;
7602 token = m->method->token;
7604 } else if (strcmp (klass->name, "MonoField") == 0) {
7605 MonoReflectionField *f = (MonoReflectionField*)obj;
7607 if (is_field_on_inst (f->field)) {
7608 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7609 int field_index = f->field - dgclass->fields;
7612 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7613 obj = dgclass->field_objects [field_index];
7614 return mono_reflection_get_token (obj);
7616 token = mono_class_get_field_token (f->field);
7617 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7618 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7620 token = mono_class_get_property_token (p->property);
7621 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7622 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7624 token = mono_class_get_event_token (p->event);
7625 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7626 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7628 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7629 } else if (strcmp (klass->name, "Module") == 0) {
7630 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7633 } else if (strcmp (klass->name, "Assembly") == 0) {
7634 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7636 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7637 MonoException *ex = mono_get_exception_not_implemented (msg);
7639 mono_raise_exception (ex);
7646 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7648 int slen, type = t->type;
7649 MonoClass *tklass = t->data.klass;
7655 case MONO_TYPE_BOOLEAN: {
7656 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7661 case MONO_TYPE_CHAR:
7663 case MONO_TYPE_I2: {
7664 guint16 *val = g_malloc (sizeof (guint16));
7669 #if SIZEOF_VOID_P == 4
7675 case MONO_TYPE_I4: {
7676 guint32 *val = g_malloc (sizeof (guint32));
7681 #if SIZEOF_VOID_P == 8
7682 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7686 case MONO_TYPE_I8: {
7687 guint64 *val = g_malloc (sizeof (guint64));
7692 case MONO_TYPE_R8: {
7693 double *val = g_malloc (sizeof (double));
7698 case MONO_TYPE_VALUETYPE:
7699 if (t->data.klass->enumtype) {
7700 type = mono_class_enum_basetype (t->data.klass)->type;
7703 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7706 case MONO_TYPE_STRING:
7707 if (*p == (char)0xFF) {
7711 slen = mono_metadata_decode_value (p, &p);
7713 return mono_string_new_len (mono_domain_get (), p, slen);
7714 case MONO_TYPE_CLASS: {
7717 if (*p == (char)0xFF) {
7722 slen = mono_metadata_decode_value (p, &p);
7723 n = g_memdup (p, slen + 1);
7725 t = mono_reflection_type_from_name (n, image);
7727 g_warning ("Cannot load type '%s'", n);
7731 return mono_type_get_object (mono_domain_get (), t);
7735 case MONO_TYPE_OBJECT: {
7738 MonoClass *subc = NULL;
7743 } else if (subt == 0x0E) {
7744 type = MONO_TYPE_STRING;
7746 } else if (subt == 0x1D) {
7747 MonoType simple_type = {{0}};
7752 /* See Partition II, Appendix B3 */
7753 etype = MONO_TYPE_OBJECT;
7754 type = MONO_TYPE_SZARRAY;
7755 simple_type.type = etype;
7756 tklass = mono_class_from_mono_type (&simple_type);
7758 } else if (subt == 0x55) {
7761 slen = mono_metadata_decode_value (p, &p);
7762 n = g_memdup (p, slen + 1);
7764 t = mono_reflection_type_from_name (n, image);
7766 g_error ("Cannot load type '%s'", n);
7769 subc = mono_class_from_mono_type (t);
7770 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7771 MonoType simple_type = {{0}};
7772 simple_type.type = subt;
7773 subc = mono_class_from_mono_type (&simple_type);
7775 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7777 val = load_cattr_value (image, &subc->byval_arg, p, end);
7778 obj = mono_object_new (mono_domain_get (), subc);
7779 g_assert (!subc->has_references);
7780 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7784 case MONO_TYPE_SZARRAY: {
7786 guint32 i, alen, basetype;
7789 if (alen == 0xffffffff) {
7793 arr = mono_array_new (mono_domain_get(), tklass, alen);
7794 basetype = tklass->byval_arg.type;
7795 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7796 basetype = mono_class_enum_basetype (tklass)->type;
7801 case MONO_TYPE_BOOLEAN:
7802 for (i = 0; i < alen; i++) {
7803 MonoBoolean val = *p++;
7804 mono_array_set (arr, MonoBoolean, i, val);
7807 case MONO_TYPE_CHAR:
7810 for (i = 0; i < alen; i++) {
7811 guint16 val = read16 (p);
7812 mono_array_set (arr, guint16, i, val);
7819 for (i = 0; i < alen; i++) {
7820 guint32 val = read32 (p);
7821 mono_array_set (arr, guint32, i, val);
7826 for (i = 0; i < alen; i++) {
7829 mono_array_set (arr, double, i, val);
7835 for (i = 0; i < alen; i++) {
7836 guint64 val = read64 (p);
7837 mono_array_set (arr, guint64, i, val);
7841 case MONO_TYPE_CLASS:
7842 case MONO_TYPE_OBJECT:
7843 case MONO_TYPE_STRING:
7844 for (i = 0; i < alen; i++) {
7845 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7846 mono_array_setref (arr, i, item);
7850 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7856 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7862 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7864 static MonoClass *klass;
7865 static MonoMethod *ctor;
7867 void *params [2], *unboxed;
7870 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7872 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7874 params [0] = mono_type_get_object (mono_domain_get (), t);
7876 retval = mono_object_new (mono_domain_get (), klass);
7877 unboxed = mono_object_unbox (retval);
7878 mono_runtime_invoke (ctor, unboxed, params, NULL);
7884 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7886 static MonoClass *klass;
7887 static MonoMethod *ctor;
7889 void *unboxed, *params [2];
7892 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7894 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7897 params [1] = typedarg;
7898 retval = mono_object_new (mono_domain_get (), klass);
7899 unboxed = mono_object_unbox (retval);
7900 mono_runtime_invoke (ctor, unboxed, params, NULL);
7906 type_is_reference (MonoType *type)
7908 switch (type->type) {
7909 case MONO_TYPE_BOOLEAN:
7910 case MONO_TYPE_CHAR:
7923 case MONO_TYPE_VALUETYPE:
7931 free_param_data (MonoMethodSignature *sig, void **params) {
7933 for (i = 0; i < sig->param_count; ++i) {
7934 if (!type_is_reference (sig->params [i]))
7935 g_free (params [i]);
7940 * Find the field index in the metadata FieldDef table.
7943 find_field_index (MonoClass *klass, MonoClassField *field) {
7946 for (i = 0; i < klass->field.count; ++i) {
7947 if (field == &klass->fields [i])
7948 return klass->field.first + 1 + i;
7954 * Find the property index in the metadata Property table.
7957 find_property_index (MonoClass *klass, MonoProperty *property) {
7960 for (i = 0; i < klass->ext->property.count; ++i) {
7961 if (property == &klass->ext->properties [i])
7962 return klass->ext->property.first + 1 + i;
7968 * Find the event index in the metadata Event table.
7971 find_event_index (MonoClass *klass, MonoEvent *event) {
7974 for (i = 0; i < klass->ext->event.count; ++i) {
7975 if (event == &klass->ext->events [i])
7976 return klass->ext->event.first + 1 + i;
7982 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7984 const char *p = (const char*)data;
7986 guint32 i, j, num_named;
7988 void *params_buf [32];
7990 MonoMethodSignature *sig;
7992 mono_class_init (method->klass);
7995 attr = mono_object_new (mono_domain_get (), method->klass);
7996 mono_runtime_invoke (method, attr, NULL, NULL);
8000 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8003 /*g_print ("got attr %s\n", method->klass->name);*/
8005 sig = mono_method_signature (method);
8006 if (sig->param_count < 32)
8007 params = params_buf;
8009 /* Allocate using GC so it gets GC tracking */
8010 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8014 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8015 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8019 attr = mono_object_new (mono_domain_get (), method->klass);
8020 mono_runtime_invoke (method, attr, params, NULL);
8021 free_param_data (method->signature, params);
8022 num_named = read16 (named);
8024 for (j = 0; j < num_named; j++) {
8026 char *name, named_type, data_type;
8027 named_type = *named++;
8028 data_type = *named++; /* type of data */
8029 if (data_type == MONO_TYPE_SZARRAY)
8030 data_type = *named++;
8031 if (data_type == MONO_TYPE_ENUM) {
8034 type_len = mono_metadata_decode_blob_size (named, &named);
8035 type_name = g_malloc (type_len + 1);
8036 memcpy (type_name, named, type_len);
8037 type_name [type_len] = 0;
8039 /* FIXME: lookup the type and check type consistency */
8042 name_len = mono_metadata_decode_blob_size (named, &named);
8043 name = g_malloc (name_len + 1);
8044 memcpy (name, named, name_len);
8045 name [name_len] = 0;
8047 if (named_type == 0x53) {
8048 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8049 void *val = load_cattr_value (image, field->type, named, &named);
8050 mono_field_set_value (attr, field, val);
8051 if (!type_is_reference (field->type))
8053 } else if (named_type == 0x54) {
8056 MonoType *prop_type;
8058 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8059 /* can we have more that 1 arg in a custom attr named property? */
8060 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8061 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8062 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8063 mono_property_set_value (prop, attr, pparams, NULL);
8064 if (!type_is_reference (prop_type))
8065 g_free (pparams [0]);
8070 if (params != params_buf)
8071 mono_gc_free_fixed (params);
8077 * mono_reflection_create_custom_attr_data_args:
8079 * Create an array of typed and named arguments from the cattr blob given by DATA.
8080 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8081 * NAMED_ARG_INFO will contain information about the named arguments.
8084 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)
8086 MonoArray *typedargs, *namedargs;
8087 MonoClass *attrklass;
8089 const char *p = (const char*)data;
8091 guint32 i, j, num_named;
8092 CattrNamedArg *arginfo = NULL;
8094 mono_class_init (method->klass);
8098 *named_arg_info = NULL;
8100 domain = mono_domain_get ();
8102 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8105 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8109 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8113 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8114 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8115 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8116 mono_array_setref (typedargs, i, obj);
8118 if (!type_is_reference (mono_method_signature (method)->params [i]))
8123 num_named = read16 (named);
8124 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8126 attrklass = method->klass;
8128 arginfo = g_new0 (CattrNamedArg, num_named);
8129 *named_arg_info = arginfo;
8131 for (j = 0; j < num_named; j++) {
8133 char *name, named_type, data_type;
8134 named_type = *named++;
8135 data_type = *named++; /* type of data */
8136 if (data_type == MONO_TYPE_SZARRAY)
8137 data_type = *named++;
8138 if (data_type == MONO_TYPE_ENUM) {
8141 type_len = mono_metadata_decode_blob_size (named, &named);
8142 type_name = g_malloc (type_len + 1);
8143 memcpy (type_name, named, type_len);
8144 type_name [type_len] = 0;
8146 /* FIXME: lookup the type and check type consistency */
8149 name_len = mono_metadata_decode_blob_size (named, &named);
8150 name = g_malloc (name_len + 1);
8151 memcpy (name, named, name_len);
8152 name [name_len] = 0;
8154 if (named_type == 0x53) {
8156 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8159 arginfo [j].type = field->type;
8160 arginfo [j].field = field;
8162 val = load_cattr_value (image, field->type, named, &named);
8163 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8164 mono_array_setref (namedargs, j, obj);
8165 if (!type_is_reference (field->type))
8167 } else if (named_type == 0x54) {
8169 MonoType *prop_type;
8170 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8173 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8174 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8176 arginfo [j].type = prop_type;
8177 arginfo [j].prop = prop;
8179 val = load_cattr_value (image, prop_type, named, &named);
8180 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8181 mono_array_setref (namedargs, j, obj);
8182 if (!type_is_reference (prop_type))
8188 *typed_args = typedargs;
8189 *named_args = namedargs;
8193 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8195 MonoArray *typedargs, *namedargs;
8196 static MonoMethod *ctor;
8200 CattrNamedArg *arginfo;
8203 mono_class_init (method->klass);
8206 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8208 domain = mono_domain_get ();
8210 /* This is for Attributes with no parameters */
8211 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8212 params [0] = mono_method_get_object (domain, method, NULL);
8213 params [1] = params [2] = NULL;
8214 mono_runtime_invoke (method, attr, params, NULL);
8218 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8219 if (!typedargs || !namedargs)
8222 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8223 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8224 MonoObject *typedarg;
8226 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8227 mono_array_setref (typedargs, i, typedarg);
8230 for (i = 0; i < mono_array_length (namedargs); ++i) {
8231 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8232 MonoObject *typedarg, *namedarg, *minfo;
8234 if (arginfo [i].prop)
8235 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8237 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8239 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8240 namedarg = create_cattr_named_arg (minfo, typedarg);
8242 mono_array_setref (namedargs, i, namedarg);
8245 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8246 params [0] = mono_method_get_object (domain, method, NULL);
8247 params [1] = typedargs;
8248 params [2] = namedargs;
8249 mono_runtime_invoke (ctor, attr, params, NULL);
8254 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8260 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8261 for (i = 0; i < cinfo->num_attrs; ++i) {
8262 if (!cinfo->attrs [i].ctor)
8263 /* The cattr type is not finished yet */
8264 /* We should include the type name but cinfo doesn't contain it */
8265 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8266 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8267 mono_array_setref (result, i, attr);
8273 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8280 for (i = 0; i < cinfo->num_attrs; ++i) {
8281 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8285 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8287 for (i = 0; i < cinfo->num_attrs; ++i) {
8288 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8289 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8290 mono_array_setref (result, n, attr);
8298 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8304 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8305 for (i = 0; i < cinfo->num_attrs; ++i) {
8306 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8307 mono_array_setref (result, i, attr);
8313 * mono_custom_attrs_from_index:
8315 * Returns: NULL if no attributes are found or if a loading error occurs.
8318 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8320 guint32 mtoken, i, len;
8321 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8323 MonoCustomAttrInfo *ainfo;
8324 GList *tmp, *list = NULL;
8327 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8329 i = mono_metadata_custom_attrs_from_index (image, idx);
8333 while (i < ca->rows) {
8334 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8336 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8339 len = g_list_length (list);
8342 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8343 ainfo->num_attrs = len;
8344 ainfo->image = image;
8345 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8346 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8347 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8348 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8349 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8350 mtoken |= MONO_TOKEN_METHOD_DEF;
8352 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8353 mtoken |= MONO_TOKEN_MEMBER_REF;
8356 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8359 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8360 if (!ainfo->attrs [i].ctor) {
8361 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8366 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8367 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8368 ainfo->attrs [i].data = (guchar*)data;
8376 mono_custom_attrs_from_method (MonoMethod *method)
8381 * An instantiated method has the same cattrs as the generic method definition.
8383 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8384 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8386 if (method->is_inflated)
8387 method = ((MonoMethodInflated *) method)->declaring;
8389 if (method->dynamic || method->klass->image->dynamic)
8390 return lookup_custom_attr (method->klass->image, method);
8393 /* Synthetic methods */
8396 idx = mono_method_get_index (method);
8397 idx <<= MONO_CUSTOM_ATTR_BITS;
8398 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8399 return mono_custom_attrs_from_index (method->klass->image, idx);
8403 mono_custom_attrs_from_class (MonoClass *klass)
8407 if (klass->generic_class)
8408 klass = klass->generic_class->container_class;
8410 if (klass->image->dynamic)
8411 return lookup_custom_attr (klass->image, klass);
8413 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8414 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8415 idx <<= MONO_CUSTOM_ATTR_BITS;
8416 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8418 idx = mono_metadata_token_index (klass->type_token);
8419 idx <<= MONO_CUSTOM_ATTR_BITS;
8420 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8422 return mono_custom_attrs_from_index (klass->image, idx);
8426 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8430 if (assembly->image->dynamic)
8431 return lookup_custom_attr (assembly->image, assembly);
8432 idx = 1; /* there is only one assembly */
8433 idx <<= MONO_CUSTOM_ATTR_BITS;
8434 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8435 return mono_custom_attrs_from_index (assembly->image, idx);
8438 static MonoCustomAttrInfo*
8439 mono_custom_attrs_from_module (MonoImage *image)
8444 return lookup_custom_attr (image, image);
8445 idx = 1; /* there is only one module */
8446 idx <<= MONO_CUSTOM_ATTR_BITS;
8447 idx |= MONO_CUSTOM_ATTR_MODULE;
8448 return mono_custom_attrs_from_index (image, idx);
8452 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8456 if (klass->image->dynamic) {
8457 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8458 return lookup_custom_attr (klass->image, property);
8460 idx = find_property_index (klass, property);
8461 idx <<= MONO_CUSTOM_ATTR_BITS;
8462 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8463 return mono_custom_attrs_from_index (klass->image, idx);
8467 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8471 if (klass->image->dynamic) {
8472 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8473 return lookup_custom_attr (klass->image, event);
8475 idx = find_event_index (klass, event);
8476 idx <<= MONO_CUSTOM_ATTR_BITS;
8477 idx |= MONO_CUSTOM_ATTR_EVENT;
8478 return mono_custom_attrs_from_index (klass->image, idx);
8482 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8485 if (klass->image->dynamic) {
8486 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8487 return lookup_custom_attr (klass->image, field);
8489 idx = find_field_index (klass, field);
8490 idx <<= MONO_CUSTOM_ATTR_BITS;
8491 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8492 return mono_custom_attrs_from_index (klass->image, idx);
8496 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8499 guint32 i, idx, method_index;
8500 guint32 param_list, param_last, param_pos, found;
8502 MonoReflectionMethodAux *aux;
8505 * An instantiated method has the same cattrs as the generic method definition.
8507 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8508 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8510 if (method->is_inflated)
8511 method = ((MonoMethodInflated *) method)->declaring;
8513 if (method->klass->image->dynamic) {
8514 MonoCustomAttrInfo *res, *ainfo;
8517 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8518 if (!aux || !aux->param_cattr)
8521 /* Need to copy since it will be freed later */
8522 ainfo = aux->param_cattr [param];
8525 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8526 res = g_malloc0 (size);
8527 memcpy (res, ainfo, size);
8531 image = method->klass->image;
8532 method_index = mono_method_get_index (method);
8533 ca = &image->tables [MONO_TABLE_METHOD];
8535 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8536 if (method_index == ca->rows) {
8537 ca = &image->tables [MONO_TABLE_PARAM];
8538 param_last = ca->rows + 1;
8540 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8541 ca = &image->tables [MONO_TABLE_PARAM];
8544 for (i = param_list; i < param_last; ++i) {
8545 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8546 if (param_pos == param) {
8554 idx <<= MONO_CUSTOM_ATTR_BITS;
8555 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8556 return mono_custom_attrs_from_index (image, idx);
8560 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8564 for (i = 0; i < ainfo->num_attrs; ++i) {
8565 klass = ainfo->attrs [i].ctor->klass;
8566 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8573 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8580 for (i = 0; i < ainfo->num_attrs; ++i) {
8581 klass = ainfo->attrs [i].ctor->klass;
8582 if (mono_class_has_parent (klass, attr_klass)) {
8587 if (attr_index == -1)
8590 attrs = mono_custom_attrs_construct (ainfo);
8592 return mono_array_get (attrs, MonoObject*, attr_index);
8598 * mono_reflection_get_custom_attrs_info:
8599 * @obj: a reflection object handle
8601 * Return the custom attribute info for attributes defined for the
8602 * reflection handle @obj. The objects.
8604 * FIXME this function leaks like a sieve for SRE objects.
8607 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8610 MonoCustomAttrInfo *cinfo = NULL;
8612 klass = obj->vtable->klass;
8613 if (klass == mono_defaults.monotype_class) {
8614 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8615 klass = mono_class_from_mono_type (type);
8616 cinfo = mono_custom_attrs_from_class (klass);
8617 } else if (strcmp ("Assembly", klass->name) == 0) {
8618 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8619 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8620 } else if (strcmp ("Module", klass->name) == 0) {
8621 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8622 cinfo = mono_custom_attrs_from_module (module->image);
8623 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8624 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8625 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8626 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8627 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8628 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8629 } else if (strcmp ("MonoField", klass->name) == 0) {
8630 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8631 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8632 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8633 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8634 cinfo = mono_custom_attrs_from_method (rmethod->method);
8635 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8636 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8637 cinfo = mono_custom_attrs_from_method (rmethod->method);
8638 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8639 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8640 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8641 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8642 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8643 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8644 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8645 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8646 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8647 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8648 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8649 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8650 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8651 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8652 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8653 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8654 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8655 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8656 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8657 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8658 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8659 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8660 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8661 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8662 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8663 } else { /* handle other types here... */
8664 g_error ("get custom attrs not yet supported for %s", klass->name);
8671 * mono_reflection_get_custom_attrs_by_type:
8672 * @obj: a reflection object handle
8674 * Return an array with all the custom attributes defined of the
8675 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8676 * of that type are returned. The objects are fully build. Return NULL if a loading error
8680 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8683 MonoCustomAttrInfo *cinfo;
8685 cinfo = mono_reflection_get_custom_attrs_info (obj);
8688 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8690 result = mono_custom_attrs_construct (cinfo);
8692 mono_custom_attrs_free (cinfo);
8694 if (mono_loader_get_last_error ())
8696 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8703 * mono_reflection_get_custom_attrs:
8704 * @obj: a reflection object handle
8706 * Return an array with all the custom attributes defined of the
8707 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8711 mono_reflection_get_custom_attrs (MonoObject *obj)
8713 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8717 * mono_reflection_get_custom_attrs_data:
8718 * @obj: a reflection obj handle
8720 * Returns an array of System.Reflection.CustomAttributeData,
8721 * which include information about attributes reflected on
8722 * types loaded using the Reflection Only methods
8725 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8728 MonoCustomAttrInfo *cinfo;
8730 cinfo = mono_reflection_get_custom_attrs_info (obj);
8732 result = mono_custom_attrs_data_construct (cinfo);
8734 mono_custom_attrs_free (cinfo);
8736 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8741 static MonoReflectionType*
8742 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8744 static MonoMethod *method_get_underlying_system_type = NULL;
8745 MonoMethod *usertype_method;
8747 if (!method_get_underlying_system_type)
8748 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8749 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8750 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8753 #ifndef DISABLE_REFLECTION_EMIT
8756 is_corlib_type (MonoClass *class)
8758 return class->image == mono_defaults.corlib;
8761 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8762 static MonoClass *cached_class; \
8764 return cached_class == _class; \
8765 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8766 cached_class = _class; \
8773 is_sre_array (MonoClass *class)
8775 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8779 is_sre_byref (MonoClass *class)
8781 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8785 is_sre_pointer (MonoClass *class)
8787 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8791 is_sre_generic_instance (MonoClass *class)
8793 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8797 is_sre_type_builder (MonoClass *class)
8799 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8803 is_sre_method_builder (MonoClass *class)
8805 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8809 is_sre_ctor_builder (MonoClass *class)
8811 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8815 is_sre_field_builder (MonoClass *class)
8817 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8821 is_sr_mono_method (MonoClass *class)
8823 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
8827 is_sr_mono_cmethod (MonoClass *class)
8829 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
8833 is_sr_mono_field (MonoClass *class)
8835 check_corlib_type_cached (class, "System.Reflection", "MonoField");
8840 mono_reflection_type_get_handle (MonoReflectionType* ref)
8848 if (is_usertype (ref)) {
8849 ref = mono_reflection_type_get_underlying_system_type (ref);
8850 if (ref == NULL || is_usertype (ref))
8856 class = mono_object_class (ref);
8858 if (is_sre_array (class)) {
8860 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8861 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8863 if (sre_array->rank == 0) //single dimentional array
8864 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8866 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8867 sre_array->type.type = res;
8869 } else if (is_sre_byref (class)) {
8871 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8872 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8874 res = &mono_class_from_mono_type (base)->this_arg;
8875 sre_byref->type.type = res;
8877 } else if (is_sre_pointer (class)) {
8879 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8880 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8882 res = &mono_ptr_class_get (base)->byval_arg;
8883 sre_pointer->type.type = res;
8885 } else if (is_sre_generic_instance (class)) {
8886 MonoType *res, **types;
8887 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8890 count = mono_array_length (gclass->type_arguments);
8891 types = g_new0 (MonoType*, count);
8892 for (i = 0; i < count; ++i) {
8893 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8894 types [i] = mono_reflection_type_get_handle (t);
8901 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
8904 gclass->type.type = res;
8908 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8915 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8917 mono_reflection_type_get_handle (type);
8921 mono_reflection_register_with_runtime (MonoReflectionType *type)
8923 MonoType *res = mono_reflection_type_get_handle (type);
8924 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
8928 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
8930 class = mono_class_from_mono_type (res);
8932 mono_loader_lock (); /*same locking as mono_type_get_object*/
8933 mono_domain_lock (domain);
8935 if (!class->image->dynamic) {
8936 mono_class_setup_supertypes (class);
8938 if (!domain->type_hash)
8939 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
8940 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
8941 mono_g_hash_table_insert (domain->type_hash, res, type);
8943 mono_domain_unlock (domain);
8944 mono_loader_unlock ();
8948 * LOCKING: Assumes the loader lock is held.
8950 static MonoMethodSignature*
8951 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8952 MonoMethodSignature *sig;
8955 count = parameters? mono_array_length (parameters): 0;
8957 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8958 sig->param_count = count;
8959 sig->sentinelpos = -1; /* FIXME */
8960 for (i = 0; i < count; ++i)
8961 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8966 * LOCKING: Assumes the loader lock is held.
8968 static MonoMethodSignature*
8969 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8970 MonoMethodSignature *sig;
8972 sig = parameters_to_signature (image, ctor->parameters);
8973 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8974 sig->ret = &mono_defaults.void_class->byval_arg;
8979 * LOCKING: Assumes the loader lock is held.
8981 static MonoMethodSignature*
8982 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8983 MonoMethodSignature *sig;
8985 sig = parameters_to_signature (image, method->parameters);
8986 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8987 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8988 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8992 static MonoMethodSignature*
8993 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8994 MonoMethodSignature *sig;
8996 sig = parameters_to_signature (NULL, method->parameters);
8997 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8998 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8999 sig->generic_param_count = 0;
9004 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9006 MonoClass *klass = mono_object_class (prop);
9007 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9008 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9009 *name = mono_string_to_utf8 (pb->name);
9010 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9012 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9013 *name = g_strdup (p->property->name);
9014 if (p->property->get)
9015 *type = mono_method_signature (p->property->get)->ret;
9017 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9022 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9024 MonoClass *klass = mono_object_class (field);
9025 if (strcmp (klass->name, "FieldBuilder") == 0) {
9026 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9027 *name = mono_string_to_utf8 (fb->name);
9028 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9030 MonoReflectionField *f = (MonoReflectionField *)field;
9031 *name = g_strdup (mono_field_get_name (f->field));
9032 *type = f->field->type;
9036 #else /* DISABLE_REFLECTION_EMIT */
9039 mono_reflection_register_with_runtime (MonoReflectionType *type)
9045 is_sre_type_builder (MonoClass *class)
9051 is_sre_generic_instance (MonoClass *class)
9056 #endif /* !DISABLE_REFLECTION_EMIT */
9059 is_usertype (MonoReflectionType *ref)
9061 MonoClass *class = mono_object_class (ref);
9062 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9065 static MonoReflectionType*
9066 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9068 if (!type || type->type)
9071 if (is_usertype (type)) {
9072 type = mono_reflection_type_get_underlying_system_type (type);
9073 if (is_usertype (type))
9074 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9080 * Encode a value in a custom attribute stream of bytes.
9081 * The value to encode is either supplied as an object in argument val
9082 * (valuetypes are boxed), or as a pointer to the data in the
9084 * @type represents the type of the value
9085 * @buffer is the start of the buffer
9086 * @p the current position in the buffer
9087 * @buflen contains the size of the buffer and is used to return the new buffer size
9088 * if this needs to be realloced.
9089 * @retbuffer and @retp return the start and the position of the buffer
9092 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9094 MonoTypeEnum simple_type;
9096 if ((p-buffer) + 10 >= *buflen) {
9099 newbuf = g_realloc (buffer, *buflen);
9100 p = newbuf + (p-buffer);
9104 argval = ((char*)arg + sizeof (MonoObject));
9105 simple_type = type->type;
9107 switch (simple_type) {
9108 case MONO_TYPE_BOOLEAN:
9113 case MONO_TYPE_CHAR:
9116 swap_with_size (p, argval, 2, 1);
9122 swap_with_size (p, argval, 4, 1);
9126 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9136 swap_with_size (p, argval, 8, 1);
9142 swap_with_size (p, argval, 8, 1);
9145 case MONO_TYPE_VALUETYPE:
9146 if (type->data.klass->enumtype) {
9147 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9150 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9153 case MONO_TYPE_STRING: {
9160 str = mono_string_to_utf8 ((MonoString*)arg);
9161 slen = strlen (str);
9162 if ((p-buffer) + 10 + slen >= *buflen) {
9166 newbuf = g_realloc (buffer, *buflen);
9167 p = newbuf + (p-buffer);
9170 mono_metadata_encode_value (slen, p, &p);
9171 memcpy (p, str, slen);
9176 case MONO_TYPE_CLASS: {
9184 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9185 slen = strlen (str);
9186 if ((p-buffer) + 10 + slen >= *buflen) {
9190 newbuf = g_realloc (buffer, *buflen);
9191 p = newbuf + (p-buffer);
9194 mono_metadata_encode_value (slen, p, &p);
9195 memcpy (p, str, slen);
9200 case MONO_TYPE_SZARRAY: {
9202 MonoClass *eclass, *arg_eclass;
9205 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9208 len = mono_array_length ((MonoArray*)arg);
9210 *p++ = (len >> 8) & 0xff;
9211 *p++ = (len >> 16) & 0xff;
9212 *p++ = (len >> 24) & 0xff;
9214 *retbuffer = buffer;
9215 eclass = type->data.klass;
9216 arg_eclass = mono_object_class (arg)->element_class;
9219 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9220 eclass = mono_defaults.object_class;
9222 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9223 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9224 int elsize = mono_class_array_element_size (arg_eclass);
9225 for (i = 0; i < len; ++i) {
9226 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9229 } else if (eclass->valuetype && arg_eclass->valuetype) {
9230 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9231 int elsize = mono_class_array_element_size (eclass);
9232 for (i = 0; i < len; ++i) {
9233 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9237 for (i = 0; i < len; ++i) {
9238 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9243 case MONO_TYPE_OBJECT: {
9249 * The parameter type is 'object' but the type of the actual
9250 * argument is not. So we have to add type information to the blob
9251 * too. This is completely undocumented in the spec.
9255 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9260 klass = mono_object_class (arg);
9262 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9265 } else if (klass->enumtype) {
9267 } else if (klass == mono_defaults.string_class) {
9268 simple_type = MONO_TYPE_STRING;
9271 } else if (klass->rank == 1) {
9273 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9274 /* See Partition II, Appendix B3 */
9277 *p++ = klass->element_class->byval_arg.type;
9278 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9280 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9281 *p++ = simple_type = klass->byval_arg.type;
9284 g_error ("unhandled type in custom attr");
9286 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9287 slen = strlen (str);
9288 if ((p-buffer) + 10 + slen >= *buflen) {
9292 newbuf = g_realloc (buffer, *buflen);
9293 p = newbuf + (p-buffer);
9296 mono_metadata_encode_value (slen, p, &p);
9297 memcpy (p, str, slen);
9300 simple_type = mono_class_enum_basetype (klass)->type;
9304 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9307 *retbuffer = buffer;
9311 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9313 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9314 char *str = type_get_qualified_name (type, NULL);
9315 int slen = strlen (str);
9319 * This seems to be optional...
9322 mono_metadata_encode_value (slen, p, &p);
9323 memcpy (p, str, slen);
9326 } else if (type->type == MONO_TYPE_OBJECT) {
9328 } else if (type->type == MONO_TYPE_CLASS) {
9329 /* it should be a type: encode_cattr_value () has the check */
9332 mono_metadata_encode_value (type->type, p, &p);
9333 if (type->type == MONO_TYPE_SZARRAY)
9334 /* See the examples in Partition VI, Annex B */
9335 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9341 #ifndef DISABLE_REFLECTION_EMIT
9343 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9346 /* Preallocate a large enough buffer */
9347 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9348 char *str = type_get_qualified_name (type, NULL);
9351 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9352 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9358 len += strlen (name);
9360 if ((p-buffer) + 20 + len >= *buflen) {
9364 newbuf = g_realloc (buffer, *buflen);
9365 p = newbuf + (p-buffer);
9369 encode_field_or_prop_type (type, p, &p);
9371 len = strlen (name);
9372 mono_metadata_encode_value (len, p, &p);
9373 memcpy (p, name, len);
9375 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9377 *retbuffer = buffer;
9381 * mono_reflection_get_custom_attrs_blob:
9382 * @ctor: custom attribute constructor
9383 * @ctorArgs: arguments o the constructor
9389 * Creates the blob of data that needs to be saved in the metadata and that represents
9390 * the custom attributed described by @ctor, @ctorArgs etc.
9391 * Returns: a Byte array representing the blob of data.
9394 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9397 MonoMethodSignature *sig;
9402 MONO_ARCH_SAVE_REGS;
9404 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9405 /* sig is freed later so allocate it in the heap */
9406 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9408 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9411 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9413 p = buffer = g_malloc (buflen);
9414 /* write the prolog */
9417 for (i = 0; i < sig->param_count; ++i) {
9418 arg = mono_array_get (ctorArgs, MonoObject*, i);
9419 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9423 i += mono_array_length (properties);
9425 i += mono_array_length (fields);
9427 *p++ = (i >> 8) & 0xff;
9430 for (i = 0; i < mono_array_length (properties); ++i) {
9434 prop = mono_array_get (properties, gpointer, i);
9435 get_prop_name_and_type (prop, &pname, &ptype);
9436 *p++ = 0x54; /* PROPERTY signature */
9437 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9444 for (i = 0; i < mono_array_length (fields); ++i) {
9448 field = mono_array_get (fields, gpointer, i);
9449 get_field_name_and_type (field, &fname, &ftype);
9450 *p++ = 0x53; /* FIELD signature */
9451 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9456 g_assert (p - buffer <= buflen);
9457 buflen = p - buffer;
9458 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9459 p = mono_array_addr (result, char, 0);
9460 memcpy (p, buffer, buflen);
9462 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9468 * mono_reflection_setup_internal_class:
9469 * @tb: a TypeBuilder object
9471 * Creates a MonoClass that represents the TypeBuilder.
9472 * This is a trick that lets us simplify a lot of reflection code
9473 * (and will allow us to support Build and Run assemblies easier).
9476 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9479 MonoClass *klass, *parent;
9481 MONO_ARCH_SAVE_REGS;
9483 RESOLVE_TYPE (tb->parent);
9485 mono_loader_lock ();
9488 /* check so we can compile corlib correctly */
9489 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9490 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9491 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9493 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9499 /* the type has already being created: it means we just have to change the parent */
9500 if (tb->type.type) {
9501 klass = mono_class_from_mono_type (tb->type.type);
9502 klass->parent = NULL;
9503 /* fool mono_class_setup_parent */
9504 klass->supertypes = NULL;
9505 mono_class_setup_parent (klass, parent);
9506 mono_class_setup_mono_type (klass);
9507 mono_loader_unlock ();
9511 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9513 klass->image = &tb->module->dynamic_image->image;
9515 klass->inited = 1; /* we lie to the runtime */
9516 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9517 if (!mono_error_ok (&error))
9519 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9520 if (!mono_error_ok (&error))
9522 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9523 klass->flags = tb->attrs;
9525 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9527 klass->element_class = klass;
9529 if (klass->reflection_info == NULL) {
9531 MOVING_GC_REGISTER (&klass->reflection_info);
9532 klass->reflection_info = tb;
9534 /* Put into cache so mono_class_get () will find it.
9535 Skip nested types as those should not be available on the global scope. */
9536 if (!tb->nesting_type) {
9537 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9539 klass->image->reflection_info_unregister_classes =
9540 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9543 g_assert (klass->reflection_info == tb);
9546 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9547 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9549 if (parent != NULL) {
9550 mono_class_setup_parent (klass, parent);
9551 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9552 const char *old_n = klass->name;
9553 /* trick to get relative numbering right when compiling corlib */
9554 klass->name = "BuildingObject";
9555 mono_class_setup_parent (klass, mono_defaults.object_class);
9556 klass->name = old_n;
9559 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9560 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9561 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9562 klass->instance_size = sizeof (MonoObject);
9563 klass->size_inited = 1;
9564 mono_class_setup_vtable_general (klass, NULL, 0);
9567 mono_class_setup_mono_type (klass);
9569 mono_class_setup_supertypes (klass);
9572 * FIXME: handle interfaces.
9575 tb->type.type = &klass->byval_arg;
9577 if (tb->nesting_type) {
9578 g_assert (tb->nesting_type->type);
9579 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9582 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9584 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9586 mono_loader_unlock ();
9590 mono_loader_unlock ();
9591 mono_error_raise_exception (&error);
9595 * mono_reflection_setup_generic_class:
9596 * @tb: a TypeBuilder object
9598 * Setup the generic class before adding the first generic parameter.
9601 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9606 * mono_reflection_create_generic_class:
9607 * @tb: a TypeBuilder object
9609 * Creates the generic class after all generic parameters have been added.
9612 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9617 MONO_ARCH_SAVE_REGS;
9619 klass = mono_class_from_mono_type (tb->type.type);
9621 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9623 if (klass->generic_container || (count == 0))
9626 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9628 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9630 klass->generic_container->owner.klass = klass;
9631 klass->generic_container->type_argc = count;
9632 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9634 klass->is_generic = 1;
9636 for (i = 0; i < count; i++) {
9637 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9638 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9639 klass->generic_container->type_params [i] = *param;
9640 /*Make sure we are a diferent type instance */
9641 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9642 klass->generic_container->type_params [i].info.pklass = NULL;
9644 g_assert (klass->generic_container->type_params [i].param.owner);
9647 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9651 * mono_reflection_create_internal_class:
9652 * @tb: a TypeBuilder object
9654 * Actually create the MonoClass that is associated with the TypeBuilder.
9657 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9661 MONO_ARCH_SAVE_REGS;
9663 klass = mono_class_from_mono_type (tb->type.type);
9665 mono_loader_lock ();
9666 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9667 MonoReflectionFieldBuilder *fb;
9669 MonoType *enum_basetype;
9671 g_assert (tb->fields != NULL);
9672 g_assert (mono_array_length (tb->fields) >= 1);
9674 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9676 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9677 mono_loader_unlock ();
9681 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9682 klass->element_class = mono_class_from_mono_type (enum_basetype);
9683 if (!klass->element_class)
9684 klass->element_class = mono_class_from_mono_type (enum_basetype);
9687 * get the element_class from the current corlib.
9689 ec = default_class_from_mono_type (enum_basetype);
9690 klass->instance_size = ec->instance_size;
9691 klass->size_inited = 1;
9693 * this is almost safe to do with enums and it's needed to be able
9694 * to create objects of the enum type (for use in SetConstant).
9696 /* FIXME: Does this mean enums can't have method overrides ? */
9697 mono_class_setup_vtable_general (klass, NULL, 0);
9699 mono_loader_unlock ();
9702 static MonoMarshalSpec*
9703 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9704 MonoReflectionMarshal *minfo)
9706 MonoMarshalSpec *res;
9708 res = image_g_new0 (image, MonoMarshalSpec, 1);
9709 res->native = minfo->type;
9711 switch (minfo->type) {
9712 case MONO_NATIVE_LPARRAY:
9713 res->data.array_data.elem_type = minfo->eltype;
9714 if (minfo->has_size) {
9715 res->data.array_data.param_num = minfo->param_num;
9716 res->data.array_data.num_elem = minfo->count;
9717 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9720 res->data.array_data.param_num = -1;
9721 res->data.array_data.num_elem = -1;
9722 res->data.array_data.elem_mult = -1;
9726 case MONO_NATIVE_BYVALTSTR:
9727 case MONO_NATIVE_BYVALARRAY:
9728 res->data.array_data.num_elem = minfo->count;
9731 case MONO_NATIVE_CUSTOM:
9732 if (minfo->marshaltyperef)
9733 res->data.custom_data.custom_name =
9734 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9736 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9745 #endif /* !DISABLE_REFLECTION_EMIT */
9747 MonoReflectionMarshal*
9748 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9749 MonoMarshalSpec *spec)
9751 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9752 MonoReflectionMarshal *minfo;
9755 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9756 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9757 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9758 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9761 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9762 minfo->type = spec->native;
9764 switch (minfo->type) {
9765 case MONO_NATIVE_LPARRAY:
9766 minfo->eltype = spec->data.array_data.elem_type;
9767 minfo->count = spec->data.array_data.num_elem;
9768 minfo->param_num = spec->data.array_data.param_num;
9771 case MONO_NATIVE_BYVALTSTR:
9772 case MONO_NATIVE_BYVALARRAY:
9773 minfo->count = spec->data.array_data.num_elem;
9776 case MONO_NATIVE_CUSTOM:
9777 if (spec->data.custom_data.custom_name) {
9778 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9780 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9782 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9784 if (spec->data.custom_data.cookie)
9785 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9795 #ifndef DISABLE_REFLECTION_EMIT
9797 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9798 ReflectionMethodBuilder *rmb,
9799 MonoMethodSignature *sig)
9803 MonoMethodNormal *pm;
9804 MonoMarshalSpec **specs;
9805 MonoReflectionMethodAux *method_aux;
9810 mono_error_init (&error);
9812 * Methods created using a MethodBuilder should have their memory allocated
9813 * inside the image mempool, while dynamic methods should have their memory
9816 dynamic = rmb->refs != NULL;
9817 image = dynamic ? NULL : klass->image;
9820 g_assert (!klass->generic_class);
9822 mono_loader_lock ();
9824 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9825 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9826 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9828 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9830 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9832 pm = (MonoMethodNormal*)m;
9834 m->dynamic = dynamic;
9836 m->flags = rmb->attrs;
9837 m->iflags = rmb->iattrs;
9838 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
9839 g_assert (mono_error_ok (&error));
9842 m->skip_visibility = rmb->skip_visibility;
9844 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9846 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9847 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9850 m->signature->pinvoke = 1;
9851 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9852 m->signature->pinvoke = 1;
9854 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9856 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
9857 g_assert (mono_error_ok (&error));
9858 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
9859 g_assert (mono_error_ok (&error));
9861 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9863 if (klass->image->dynamic)
9864 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9866 mono_loader_unlock ();
9869 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9870 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9871 MonoMethodHeader *header;
9873 gint32 max_stack, i;
9874 gint32 num_locals = 0;
9875 gint32 num_clauses = 0;
9879 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9880 code_size = rmb->ilgen->code_len;
9881 max_stack = rmb->ilgen->max_stack;
9882 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9883 if (rmb->ilgen->ex_handlers)
9884 num_clauses = method_count_clauses (rmb->ilgen);
9887 code = mono_array_addr (rmb->code, guint8, 0);
9888 code_size = mono_array_length (rmb->code);
9889 /* we probably need to run a verifier on the code... */
9899 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9900 header->code_size = code_size;
9901 header->code = image_g_malloc (image, code_size);
9902 memcpy ((char*)header->code, code, code_size);
9903 header->max_stack = max_stack;
9904 header->init_locals = rmb->init_locals;
9905 header->num_locals = num_locals;
9907 for (i = 0; i < num_locals; ++i) {
9908 MonoReflectionLocalBuilder *lb =
9909 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9911 header->locals [i] = image_g_new0 (image, MonoType, 1);
9912 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9915 header->num_clauses = num_clauses;
9917 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9918 rmb->ilgen, num_clauses);
9921 pm->header = header;
9924 if (rmb->generic_params) {
9925 int count = mono_array_length (rmb->generic_params);
9926 MonoGenericContainer *container = rmb->generic_container;
9928 g_assert (container);
9930 container->type_argc = count;
9931 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9932 container->owner.method = m;
9934 m->is_generic = TRUE;
9935 mono_method_set_generic_container (m, container);
9937 for (i = 0; i < count; i++) {
9938 MonoReflectionGenericParam *gp =
9939 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9940 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9941 container->type_params [i] = *param;
9944 if (klass->generic_container) {
9945 container->parent = klass->generic_container;
9946 container->context.class_inst = klass->generic_container->context.class_inst;
9948 container->context.method_inst = mono_get_shared_generic_inst (container);
9952 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9956 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9958 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9959 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9960 for (i = 0; i < rmb->nrefs; ++i)
9961 data [i + 1] = rmb->refs [i];
9966 /* Parameter info */
9969 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9970 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9971 for (i = 0; i <= m->signature->param_count; ++i) {
9972 MonoReflectionParamBuilder *pb;
9973 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9974 if ((i > 0) && (pb->attrs)) {
9975 /* Make a copy since it might point to a shared type structure */
9976 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9977 m->signature->params [i - 1]->attrs = pb->attrs;
9980 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9981 MonoDynamicImage *assembly;
9982 guint32 idx, def_type, len;
9986 if (!method_aux->param_defaults) {
9987 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9988 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9990 assembly = (MonoDynamicImage*)klass->image;
9991 idx = encode_constant (assembly, pb->def_value, &def_type);
9992 /* Copy the data from the blob since it might get realloc-ed */
9993 p = assembly->blob.data + idx;
9994 len = mono_metadata_decode_blob_size (p, &p2);
9996 method_aux->param_defaults [i] = image_g_malloc (image, len);
9997 method_aux->param_default_types [i] = def_type;
9998 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10002 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10003 g_assert (mono_error_ok (&error));
10006 if (!method_aux->param_cattr)
10007 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10008 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10014 /* Parameter marshalling */
10017 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10018 MonoReflectionParamBuilder *pb;
10019 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10020 if (pb->marshal_info) {
10022 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10023 specs [pb->position] =
10024 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10028 if (specs != NULL) {
10030 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10031 method_aux->param_marshall = specs;
10034 if (klass->image->dynamic && method_aux)
10035 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10037 mono_loader_unlock ();
10043 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10045 ReflectionMethodBuilder rmb;
10046 MonoMethodSignature *sig;
10048 mono_loader_lock ();
10049 sig = ctor_builder_to_signature (klass->image, mb);
10050 mono_loader_unlock ();
10052 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10054 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10055 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10057 /* If we are in a generic class, we might be called multiple times from inflate_method */
10058 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10059 /* ilgen is no longer needed */
10063 return mb->mhandle;
10067 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10069 ReflectionMethodBuilder rmb;
10070 MonoMethodSignature *sig;
10072 mono_loader_lock ();
10073 sig = method_builder_to_signature (klass->image, mb);
10074 mono_loader_unlock ();
10076 reflection_methodbuilder_from_method_builder (&rmb, mb);
10078 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10079 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10081 /* If we are in a generic class, we might be called multiple times from inflate_method */
10082 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10083 /* ilgen is no longer needed */
10086 return mb->mhandle;
10089 static MonoClassField*
10090 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10092 MonoClassField *field;
10095 field = g_new0 (MonoClassField, 1);
10097 field->name = mono_string_to_utf8 (fb->name);
10098 if (fb->attrs || fb->modreq || fb->modopt) {
10099 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10100 field->type->attrs = fb->attrs;
10102 g_assert (klass->image->dynamic);
10103 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10104 g_free (field->type);
10105 field->type = custom;
10107 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10109 if (fb->offset != -1)
10110 field->offset = fb->offset;
10111 field->parent = klass;
10112 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10114 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10121 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10124 MonoReflectionTypeBuilder *tb = NULL;
10125 gboolean is_dynamic = FALSE;
10126 MonoDomain *domain;
10127 MonoClass *geninst;
10129 mono_loader_lock ();
10131 domain = mono_object_domain (type);
10133 if (is_sre_type_builder (mono_object_class (type))) {
10134 tb = (MonoReflectionTypeBuilder *) type;
10137 } else if (is_sre_generic_instance (mono_object_class (type))) {
10138 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10139 MonoReflectionType *gtd = rgi->generic_type;
10141 if (is_sre_type_builder (mono_object_class (gtd))) {
10142 tb = (MonoReflectionTypeBuilder *)gtd;
10147 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10148 if (tb && tb->generic_container)
10149 mono_reflection_create_generic_class (tb);
10151 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10152 if (!klass->generic_container) {
10153 mono_loader_unlock ();
10157 if (klass->wastypebuilder) {
10158 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
10163 mono_loader_unlock ();
10165 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10167 return &geninst->byval_arg;
10171 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10173 MonoGenericClass *gclass;
10174 MonoGenericInst *inst;
10176 g_assert (klass->generic_container);
10178 inst = mono_metadata_get_generic_inst (type_argc, types);
10179 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10181 return mono_generic_class_get_class (gclass);
10184 MonoReflectionMethod*
10185 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10188 MonoMethod *method, *inflated;
10189 MonoMethodInflated *imethod;
10190 MonoGenericContext tmp_context;
10191 MonoGenericInst *ginst;
10192 MonoType **type_argv;
10195 MONO_ARCH_SAVE_REGS;
10197 /*FIXME but this no longer should happen*/
10198 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10199 #ifndef DISABLE_REFLECTION_EMIT
10200 MonoReflectionMethodBuilder *mb = NULL;
10201 MonoReflectionTypeBuilder *tb;
10204 mb = (MonoReflectionMethodBuilder *) rmethod;
10205 tb = (MonoReflectionTypeBuilder *) mb->type;
10206 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10208 method = methodbuilder_to_mono_method (klass, mb);
10210 g_assert_not_reached ();
10214 method = rmethod->method;
10217 klass = method->klass;
10219 if (method->is_inflated)
10220 method = ((MonoMethodInflated *) method)->declaring;
10222 count = mono_method_signature (method)->generic_param_count;
10223 if (count != mono_array_length (types))
10226 type_argv = g_new0 (MonoType *, count);
10227 for (i = 0; i < count; i++) {
10228 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10229 type_argv [i] = mono_reflection_type_get_handle (garg);
10231 ginst = mono_metadata_get_generic_inst (count, type_argv);
10232 g_free (type_argv);
10234 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10235 tmp_context.method_inst = ginst;
10237 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10238 imethod = (MonoMethodInflated *) inflated;
10240 /*FIXME but I think this is no longer necessary*/
10241 if (method->klass->image->dynamic) {
10242 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10244 * This table maps metadata structures representing inflated methods/fields
10245 * to the reflection objects representing their generic definitions.
10247 mono_loader_lock ();
10248 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10249 mono_loader_unlock ();
10252 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10255 #ifndef DISABLE_REFLECTION_EMIT
10257 static MonoMethod *
10258 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10260 MonoMethodInflated *imethod;
10261 MonoGenericContext *context;
10265 * With generic code sharing the klass might not be inflated.
10266 * This can happen because classes inflated with their own
10267 * type arguments are "normalized" to the uninflated class.
10269 if (!klass->generic_class)
10272 context = mono_class_get_context (klass);
10274 if (klass->method.count) {
10275 /* Find the already created inflated method */
10276 for (i = 0; i < klass->method.count; ++i) {
10277 g_assert (klass->methods [i]->is_inflated);
10278 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10281 g_assert (i < klass->method.count);
10282 imethod = (MonoMethodInflated*)klass->methods [i];
10284 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10287 if (method->is_generic && method->klass->image->dynamic) {
10288 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10290 mono_loader_lock ();
10291 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10292 mono_loader_unlock ();
10294 return (MonoMethod *) imethod;
10297 static MonoMethod *
10298 inflate_method (MonoReflectionType *type, MonoObject *obj)
10300 MonoMethod *method;
10303 MonoClass *type_class = mono_object_class (type);
10305 if (is_sre_generic_instance (type_class)) {
10306 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10307 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10308 } else if (is_sre_type_builder (type_class)) {
10309 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10310 } else if (type->type) {
10311 gklass = mono_class_from_mono_type (type->type);
10312 gklass = mono_class_get_generic_type_definition (gklass);
10314 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10317 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10318 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10319 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10321 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10322 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10323 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10324 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10325 method = ((MonoReflectionMethod *) obj)->method;
10327 method = NULL; /* prevent compiler warning */
10328 g_error ("can't handle type %s", obj->vtable->klass->name);
10331 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10334 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10336 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10337 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10340 MonoGenericClass *gclass;
10341 MonoDynamicGenericClass *dgclass;
10342 MonoClass *klass, *gklass;
10346 MONO_ARCH_SAVE_REGS;
10348 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10349 klass = mono_class_from_mono_type (gtype);
10350 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10351 gclass = gtype->data.generic_class;
10353 if (!gclass->is_dynamic)
10356 dgclass = (MonoDynamicGenericClass *) gclass;
10358 if (dgclass->initialized)
10361 gklass = gclass->container_class;
10362 mono_class_init (gklass);
10364 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10365 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10366 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10368 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10369 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10370 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10371 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10372 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10374 for (i = 0; i < dgclass->count_methods; i++) {
10375 MonoObject *obj = mono_array_get (methods, gpointer, i);
10377 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10380 for (i = 0; i < dgclass->count_ctors; i++) {
10381 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10383 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10386 for (i = 0; i < dgclass->count_fields; i++) {
10387 MonoObject *obj = mono_array_get (fields, gpointer, i);
10388 MonoClassField *field, *inflated_field = NULL;
10390 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10391 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10392 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10393 field = ((MonoReflectionField *) obj)->field;
10395 field = NULL; /* prevent compiler warning */
10396 g_assert_not_reached ();
10399 dgclass->fields [i] = *field;
10400 dgclass->fields [i].parent = klass;
10401 dgclass->fields [i].type = mono_class_inflate_generic_type (
10402 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10403 dgclass->field_generic_types [i] = field->type;
10404 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10405 dgclass->field_objects [i] = obj;
10407 if (inflated_field) {
10408 g_free (inflated_field);
10410 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10414 dgclass->initialized = TRUE;
10418 fix_partial_generic_class (MonoClass *klass)
10420 MonoClass *gklass = klass->generic_class->container_class;
10421 MonoDynamicGenericClass *dgclass;
10424 if (klass->wastypebuilder)
10427 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10429 if (!dgclass->initialized)
10432 if (klass->method.count != gklass->method.count) {
10433 klass->method.count = gklass->method.count;
10434 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10436 for (i = 0; i < klass->method.count; i++) {
10437 klass->methods [i] = mono_class_inflate_generic_method_full (
10438 gklass->methods [i], klass, mono_class_get_context (klass));
10442 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10443 klass->interface_count = gklass->interface_count;
10444 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10445 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10447 for (i = 0; i < gklass->interface_count; ++i) {
10448 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10449 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10450 mono_metadata_free_type (iface_type);
10452 ensure_runtime_vtable (klass->interfaces [i]);
10454 klass->interfaces_inited = 1;
10457 if (klass->field.count != gklass->field.count) {
10458 klass->field.count = gklass->field.count;
10459 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10461 for (i = 0; i < klass->field.count; i++) {
10462 klass->fields [i] = gklass->fields [i];
10463 klass->fields [i].parent = klass;
10464 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10468 /*We can only finish with this klass once it's parent has as well*/
10469 if (gklass->wastypebuilder)
10470 klass->wastypebuilder = TRUE;
10475 ensure_generic_class_runtime_vtable (MonoClass *klass)
10477 MonoClass *gklass = klass->generic_class->container_class;
10479 ensure_runtime_vtable (gklass);
10481 fix_partial_generic_class (klass);
10485 ensure_runtime_vtable (MonoClass *klass)
10487 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10490 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10493 ensure_runtime_vtable (klass->parent);
10496 num = tb->ctors? mono_array_length (tb->ctors): 0;
10497 num += tb->num_methods;
10498 klass->method.count = num;
10499 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10500 num = tb->ctors? mono_array_length (tb->ctors): 0;
10501 for (i = 0; i < num; ++i)
10502 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10503 num = tb->num_methods;
10505 for (i = 0; i < num; ++i)
10506 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10508 if (tb->interfaces) {
10509 klass->interface_count = mono_array_length (tb->interfaces);
10510 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10511 for (i = 0; i < klass->interface_count; ++i) {
10512 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10513 klass->interfaces [i] = mono_class_from_mono_type (iface);
10514 ensure_runtime_vtable (klass->interfaces [i]);
10516 klass->interfaces_inited = 1;
10518 } else if (klass->generic_class){
10519 ensure_generic_class_runtime_vtable (klass);
10522 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10523 for (i = 0; i < klass->method.count; ++i)
10524 klass->methods [i]->slot = i;
10526 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10527 mono_class_setup_interface_offsets (klass);
10528 mono_class_setup_interface_id (klass);
10532 * The generic vtable is needed even if image->run is not set since some
10533 * runtime code like ves_icall_Type_GetMethodsByName depends on
10534 * method->slot being defined.
10538 * tb->methods could not be freed since it is used for determining
10539 * overrides during dynamic vtable construction.
10544 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10546 MonoReflectionTypeBuilder *tb;
10550 *num_overrides = 0;
10552 g_assert (klass->image->dynamic);
10554 if (!klass->reflection_info)
10557 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10559 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10563 for (i = 0; i < tb->num_methods; ++i) {
10564 MonoReflectionMethodBuilder *mb =
10565 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10566 if (mb->override_method)
10572 *overrides = g_new0 (MonoMethod*, onum * 2);
10575 for (i = 0; i < tb->num_methods; ++i) {
10576 MonoReflectionMethodBuilder *mb =
10577 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10578 if (mb->override_method) {
10579 (*overrides) [onum * 2] =
10580 mb->override_method->method;
10581 (*overrides) [onum * 2 + 1] =
10584 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10585 g_assert (mb->override_method->method);
10586 g_assert (mb->mhandle);
10593 *num_overrides = onum;
10597 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10599 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10600 MonoReflectionFieldBuilder *fb;
10601 MonoClassField *field;
10602 MonoImage *image = klass->image;
10603 const char *p, *p2;
10605 guint32 len, idx, real_size = 0;
10607 klass->field.count = tb->num_fields;
10608 klass->field.first = 0;
10610 mono_error_init (error);
10612 if (tb->class_size) {
10613 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10614 klass->packing_size = tb->packing_size;
10615 real_size = klass->instance_size + tb->class_size;
10618 if (!klass->field.count) {
10619 klass->instance_size = MAX (klass->instance_size, real_size);
10623 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10624 mono_class_alloc_ext (klass);
10625 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10627 for (i = 0; i < klass->field.count; ++i) {
10628 fb = mono_array_get (tb->fields, gpointer, i);
10629 field = &klass->fields [i];
10630 field->name = mono_string_to_utf8_image (image, fb->name, error);
10631 if (!mono_error_ok (error))
10634 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10635 field->type->attrs = fb->attrs;
10637 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10639 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10640 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10641 if (fb->offset != -1)
10642 field->offset = fb->offset;
10643 field->parent = klass;
10644 fb->handle = field;
10645 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10647 if (fb->def_value) {
10648 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10649 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10650 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10651 /* Copy the data from the blob since it might get realloc-ed */
10652 p = assembly->blob.data + idx;
10653 len = mono_metadata_decode_blob_size (p, &p2);
10655 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10656 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10660 klass->instance_size = MAX (klass->instance_size, real_size);
10661 mono_class_layout_fields (klass);
10665 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10667 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10668 MonoReflectionPropertyBuilder *pb;
10669 MonoImage *image = klass->image;
10670 MonoProperty *properties;
10673 mono_error_init (error);
10676 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10678 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10679 klass->ext->property.first = 0;
10681 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10682 klass->ext->properties = properties;
10683 for (i = 0; i < klass->ext->property.count; ++i) {
10684 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10685 properties [i].parent = klass;
10686 properties [i].attrs = pb->attrs;
10687 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10688 if (!mono_error_ok (error))
10690 if (pb->get_method)
10691 properties [i].get = pb->get_method->mhandle;
10692 if (pb->set_method)
10693 properties [i].set = pb->set_method->mhandle;
10695 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10699 MonoReflectionEvent *
10700 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10702 MonoEvent *event = g_new0 (MonoEvent, 1);
10706 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10708 event->parent = klass;
10709 event->attrs = eb->attrs;
10710 event->name = mono_string_to_utf8 (eb->name);
10711 if (eb->add_method)
10712 event->add = eb->add_method->mhandle;
10713 if (eb->remove_method)
10714 event->remove = eb->remove_method->mhandle;
10715 if (eb->raise_method)
10716 event->raise = eb->raise_method->mhandle;
10718 if (eb->other_methods) {
10719 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10720 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10721 MonoReflectionMethodBuilder *mb =
10722 mono_array_get (eb->other_methods,
10723 MonoReflectionMethodBuilder*, j);
10724 event->other [j] = mb->mhandle;
10728 return mono_event_get_object (mono_object_domain (tb), klass, event);
10732 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10734 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10735 MonoReflectionEventBuilder *eb;
10736 MonoImage *image = klass->image;
10740 mono_error_init (error);
10743 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10745 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10746 klass->ext->event.first = 0;
10748 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10749 klass->ext->events = events;
10750 for (i = 0; i < klass->ext->event.count; ++i) {
10751 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10752 events [i].parent = klass;
10753 events [i].attrs = eb->attrs;
10754 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10755 if (!mono_error_ok (error))
10757 if (eb->add_method)
10758 events [i].add = eb->add_method->mhandle;
10759 if (eb->remove_method)
10760 events [i].remove = eb->remove_method->mhandle;
10761 if (eb->raise_method)
10762 events [i].raise = eb->raise_method->mhandle;
10764 if (eb->other_methods) {
10765 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10766 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10767 MonoReflectionMethodBuilder *mb =
10768 mono_array_get (eb->other_methods,
10769 MonoReflectionMethodBuilder*, j);
10770 events [i].other [j] = mb->mhandle;
10773 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10778 remove_instantiations_of_and_ensure_contents (gpointer key,
10780 gpointer user_data)
10782 MonoType *type = (MonoType*)key;
10783 MonoClass *klass = (MonoClass*)user_data;
10785 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
10786 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
10793 check_array_for_usertypes (MonoArray *arr)
10800 for (i = 0; i < mono_array_length (arr); ++i)
10801 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10804 MonoReflectionType*
10805 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10809 MonoDomain* domain;
10810 MonoReflectionType* res;
10813 MONO_ARCH_SAVE_REGS;
10815 domain = mono_object_domain (tb);
10816 klass = mono_class_from_mono_type (tb->type.type);
10819 * Check for user defined Type subclasses.
10821 RESOLVE_TYPE (tb->parent);
10822 check_array_for_usertypes (tb->interfaces);
10824 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10825 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10827 RESOLVE_TYPE (fb->type);
10828 check_array_for_usertypes (fb->modreq);
10829 check_array_for_usertypes (fb->modopt);
10830 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10831 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10836 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10837 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10839 RESOLVE_TYPE (mb->rtype);
10840 check_array_for_usertypes (mb->return_modreq);
10841 check_array_for_usertypes (mb->return_modopt);
10842 check_array_for_usertypes (mb->parameters);
10843 if (mb->param_modreq)
10844 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10845 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10846 if (mb->param_modopt)
10847 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10848 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10853 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10854 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10856 check_array_for_usertypes (mb->parameters);
10857 if (mb->param_modreq)
10858 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10859 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10860 if (mb->param_modopt)
10861 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10862 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10867 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10870 * we need to lock the domain because the lock will be taken inside
10871 * So, we need to keep the locking order correct.
10873 mono_loader_lock ();
10874 mono_domain_lock (domain);
10875 if (klass->wastypebuilder) {
10876 mono_domain_unlock (domain);
10877 mono_loader_unlock ();
10878 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10881 * Fields to set in klass:
10882 * the various flags: delegate/unicode/contextbound etc.
10884 klass->flags = tb->attrs;
10885 klass->has_cctor = 1;
10886 klass->has_finalize = 1;
10889 if (!((MonoDynamicImage*)klass->image)->run) {
10890 if (klass->generic_container) {
10891 /* FIXME: The code below can't handle generic classes */
10892 klass->wastypebuilder = TRUE;
10893 mono_loader_unlock ();
10894 mono_domain_unlock (domain);
10895 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10900 /* enums are done right away */
10901 if (!klass->enumtype)
10902 ensure_runtime_vtable (klass);
10904 if (tb->subtypes) {
10905 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10906 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10907 mono_class_alloc_ext (klass);
10908 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)));
10912 klass->nested_classes_inited = TRUE;
10914 /* fields and object layout */
10915 if (klass->parent) {
10916 if (!klass->parent->size_inited)
10917 mono_class_init (klass->parent);
10918 klass->instance_size = klass->parent->instance_size;
10919 klass->sizes.class_size = 0;
10920 klass->min_align = klass->parent->min_align;
10921 /* if the type has no fields we won't call the field_setup
10922 * routine which sets up klass->has_references.
10924 klass->has_references |= klass->parent->has_references;
10926 klass->instance_size = sizeof (MonoObject);
10927 klass->min_align = 1;
10930 /* FIXME: handle packing_size and instance_size */
10931 typebuilder_setup_fields (klass, &error);
10932 if (!mono_error_ok (&error))
10934 typebuilder_setup_properties (klass, &error);
10935 if (!mono_error_ok (&error))
10938 typebuilder_setup_events (klass, &error);
10939 if (!mono_error_ok (&error))
10942 klass->wastypebuilder = TRUE;
10945 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10946 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10947 * we want to return normal System.MonoType objects, so clear these out from the cache.
10949 * Together with this we must ensure the contents of all instances to match the created type.
10951 if (domain->type_hash && klass->generic_container)
10952 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
10954 mono_domain_unlock (domain);
10955 mono_loader_unlock ();
10957 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10958 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10959 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10962 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10963 g_assert (res != (MonoReflectionType*)tb);
10968 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10969 klass->wastypebuilder = TRUE;
10970 mono_domain_unlock (domain);
10971 mono_loader_unlock ();
10972 mono_error_raise_exception (&error);
10977 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10979 MonoGenericParamFull *param;
10983 MONO_ARCH_SAVE_REGS;
10985 param = g_new0 (MonoGenericParamFull, 1);
10987 if (gparam->mbuilder) {
10988 if (!gparam->mbuilder->generic_container) {
10989 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10990 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10991 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10992 gparam->mbuilder->generic_container->is_method = TRUE;
10994 * Cannot set owner.method, since the MonoMethod is not created yet.
10995 * Set the image field instead, so type_in_image () works.
10997 gparam->mbuilder->generic_container->image = klass->image;
10999 param->param.owner = gparam->mbuilder->generic_container;
11000 } else if (gparam->tbuilder) {
11001 if (!gparam->tbuilder->generic_container) {
11002 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11003 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11004 gparam->tbuilder->generic_container->owner.klass = klass;
11006 param->param.owner = gparam->tbuilder->generic_container;
11009 param->info.name = mono_string_to_utf8 (gparam->name);
11010 param->param.num = gparam->index;
11012 image = &gparam->tbuilder->module->dynamic_image->image;
11013 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11015 gparam->type.type = &pklass->byval_arg;
11017 MOVING_GC_REGISTER (&pklass->reflection_info);
11018 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
11019 mono_image_lock (image);
11020 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11021 mono_image_unlock (image);
11025 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11027 MonoReflectionModuleBuilder *module = sig->module;
11028 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11029 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11034 check_array_for_usertypes (sig->arguments);
11036 sigbuffer_init (&buf, 32);
11038 sigbuffer_add_value (&buf, 0x07);
11039 sigbuffer_add_value (&buf, na);
11040 if (assembly != NULL){
11041 for (i = 0; i < na; ++i) {
11042 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11043 encode_reflection_type (assembly, type, &buf);
11047 buflen = buf.p - buf.buf;
11048 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11049 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11050 sigbuffer_free (&buf);
11056 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11058 MonoDynamicImage *assembly = sig->module->dynamic_image;
11059 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11064 check_array_for_usertypes (sig->arguments);
11066 sigbuffer_init (&buf, 32);
11068 sigbuffer_add_value (&buf, 0x06);
11069 for (i = 0; i < na; ++i) {
11070 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11071 encode_reflection_type (assembly, type, &buf);
11074 buflen = buf.p - buf.buf;
11075 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11076 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11077 sigbuffer_free (&buf);
11083 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11085 ReflectionMethodBuilder rmb;
11086 MonoMethodSignature *sig;
11091 sig = dynamic_method_to_signature (mb);
11093 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11096 * Resolve references.
11099 * Every second entry in the refs array is reserved for storing handle_class,
11100 * which is needed by the ldtoken implementation in the JIT.
11102 rmb.nrefs = mb->nrefs;
11103 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11104 for (i = 0; i < mb->nrefs; i += 2) {
11105 MonoClass *handle_class;
11107 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11109 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11110 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11112 * The referenced DynamicMethod should already be created by the managed
11113 * code, except in the case of circular references. In that case, we store
11114 * method in the refs array, and fix it up later when the referenced
11115 * DynamicMethod is created.
11117 if (method->mhandle) {
11118 ref = method->mhandle;
11120 /* FIXME: GC object stored in unmanaged memory */
11123 /* FIXME: GC object stored in unmanaged memory */
11124 method->referenced_by = g_slist_append (method->referenced_by, mb);
11126 handle_class = mono_defaults.methodhandle_class;
11128 MonoException *ex = NULL;
11129 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11131 ex = mono_get_exception_type_load (NULL, NULL);
11132 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11133 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11137 mono_raise_exception (ex);
11142 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11143 rmb.refs [i + 1] = handle_class;
11146 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11148 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11150 /* Fix up refs entries pointing at us */
11151 for (l = mb->referenced_by; l; l = l->next) {
11152 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11153 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11156 g_assert (method->mhandle);
11158 data = (gpointer*)wrapper->method_data;
11159 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11160 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11161 data [i + 1] = mb->mhandle;
11164 g_slist_free (mb->referenced_by);
11168 /* ilgen is no longer needed */
11172 #endif /* DISABLE_REFLECTION_EMIT */
11175 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11180 mono_runtime_free_method (
11181 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11186 * mono_reflection_is_valid_dynamic_token:
11188 * Returns TRUE if token is valid.
11192 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11194 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11197 #ifndef DISABLE_REFLECTION_EMIT
11200 * mono_reflection_lookup_dynamic_token:
11202 * Finish the Builder object pointed to by TOKEN and return the corresponding
11203 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11204 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11207 * LOCKING: Take the loader lock
11210 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11212 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11216 mono_loader_lock ();
11217 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11218 mono_loader_unlock ();
11221 g_error ("Could not find required dynamic token 0x%08x", token);
11227 handle_class = &klass;
11228 return resolve_object (image, obj, handle_class, context);
11232 * ensure_complete_type:
11234 * Ensure that KLASS is completed if it is a dynamic type, or references
11238 ensure_complete_type (MonoClass *klass)
11240 if (klass->image->dynamic && !klass->wastypebuilder) {
11241 MonoReflectionTypeBuilder *tb = klass->reflection_info;
11243 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11245 // Asserting here could break a lot of code
11246 //g_assert (klass->wastypebuilder);
11249 if (klass->generic_class) {
11250 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11253 for (i = 0; i < inst->type_argc; ++i) {
11254 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11260 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11262 gpointer result = NULL;
11264 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11265 result = mono_string_intern ((MonoString*)obj);
11266 *handle_class = mono_defaults.string_class;
11268 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11269 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11271 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11272 result = mono_class_from_mono_type (inflated);
11273 mono_metadata_free_type (inflated);
11275 result = mono_class_from_mono_type (type);
11277 *handle_class = mono_defaults.typehandle_class;
11279 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11280 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11281 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11282 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11283 result = ((MonoReflectionMethod*)obj)->method;
11285 result = mono_class_inflate_generic_method (result, context);
11286 *handle_class = mono_defaults.methodhandle_class;
11288 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11289 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11290 result = mb->mhandle;
11292 /* Type is not yet created */
11293 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11295 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11298 * Hopefully this has been filled in by calling CreateType() on the
11302 * TODO: This won't work if the application finishes another
11303 * TypeBuilder instance instead of this one.
11305 result = mb->mhandle;
11308 result = mono_class_inflate_generic_method (result, context);
11309 *handle_class = mono_defaults.methodhandle_class;
11310 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11311 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11313 result = cb->mhandle;
11315 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11317 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11318 result = cb->mhandle;
11321 result = mono_class_inflate_generic_method (result, context);
11322 *handle_class = mono_defaults.methodhandle_class;
11323 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11324 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11326 ensure_complete_type (field->parent);
11328 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11329 MonoClass *class = mono_class_from_mono_type (inflated);
11330 MonoClassField *inflated_field;
11331 gpointer iter = NULL;
11332 mono_metadata_free_type (inflated);
11333 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11334 if (!strcmp (field->name, inflated_field->name))
11337 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11338 result = inflated_field;
11342 *handle_class = mono_defaults.fieldhandle_class;
11344 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11345 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11346 result = fb->handle;
11349 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11351 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11352 result = fb->handle;
11355 if (fb->handle && fb->handle->parent->generic_container) {
11356 MonoClass *klass = fb->handle->parent;
11357 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11358 MonoClass *inflated = mono_class_from_mono_type (type);
11360 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11362 mono_metadata_free_type (type);
11364 *handle_class = mono_defaults.fieldhandle_class;
11365 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11366 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11367 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11370 klass = type->data.klass;
11371 if (klass->wastypebuilder) {
11372 /* Already created */
11376 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11377 result = type->data.klass;
11380 *handle_class = mono_defaults.typehandle_class;
11381 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11382 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11383 MonoMethodSignature *sig;
11386 if (helper->arguments)
11387 nargs = mono_array_length (helper->arguments);
11391 sig = mono_metadata_signature_alloc (image, nargs);
11392 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11393 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11395 if (helper->unmanaged_call_conv) { /* unmanaged */
11396 sig->call_convention = helper->unmanaged_call_conv - 1;
11397 sig->pinvoke = TRUE;
11398 } else if (helper->call_conv & 0x02) {
11399 sig->call_convention = MONO_CALL_VARARG;
11401 sig->call_convention = MONO_CALL_DEFAULT;
11404 sig->param_count = nargs;
11405 /* TODO: Copy type ? */
11406 sig->ret = helper->return_type->type;
11407 for (i = 0; i < nargs; ++i)
11408 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11411 *handle_class = NULL;
11412 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11413 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11414 /* Already created by the managed code */
11415 g_assert (method->mhandle);
11416 result = method->mhandle;
11417 *handle_class = mono_defaults.methodhandle_class;
11418 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11419 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11420 type = mono_class_inflate_generic_type (type, context);
11421 result = mono_class_from_mono_type (type);
11422 *handle_class = mono_defaults.typehandle_class;
11424 mono_metadata_free_type (type);
11425 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11426 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11427 type = mono_class_inflate_generic_type (type, context);
11428 result = mono_class_from_mono_type (type);
11429 *handle_class = mono_defaults.typehandle_class;
11431 mono_metadata_free_type (type);
11432 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11433 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11434 MonoClass *inflated;
11436 MonoClassField *field;
11438 if (is_sre_field_builder (mono_object_class (f->fb)))
11439 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11440 else if (is_sr_mono_field (mono_object_class (f->fb)))
11441 field = ((MonoReflectionField*)f->fb)->field;
11443 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)));
11445 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11446 inflated = mono_class_from_mono_type (type);
11448 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11449 ensure_complete_type (field->parent);
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);