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/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
46 static gboolean is_usertype (MonoReflectionType *ref);
47 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
55 #define TEXT_OFFSET 512
56 #define CLI_H_SIZE 136
57 #define FILE_ALIGN 512
58 #define VIRT_ALIGN 8192
59 #define START_TEXT_RVA 0x00002000
62 MonoReflectionILGen *ilgen;
63 MonoReflectionType *rtype;
64 MonoArray *parameters;
65 MonoArray *generic_params;
66 MonoGenericContainer *generic_container;
72 guint32 *table_idx; /* note: it's a pointer */
76 MonoBoolean init_locals;
77 MonoBoolean skip_visibility;
78 MonoArray *return_modreq;
79 MonoArray *return_modopt;
80 MonoArray *param_modreq;
81 MonoArray *param_modopt;
82 MonoArray *permissions;
87 int charset, extra_flags, native_cc;
88 MonoString *dll, *dllentry;
89 } ReflectionMethodBuilder;
93 MonoReflectionGenericParam *gparam;
94 } GenericParamTableEntry;
96 const unsigned char table_sizes [MONO_TABLE_NUM] = {
106 MONO_INTERFACEIMPL_SIZE,
107 MONO_MEMBERREF_SIZE, /* 0x0A */
109 MONO_CUSTOM_ATTR_SIZE,
110 MONO_FIELD_MARSHAL_SIZE,
111 MONO_DECL_SECURITY_SIZE,
112 MONO_CLASS_LAYOUT_SIZE,
113 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
114 MONO_STAND_ALONE_SIGNATURE_SIZE,
118 MONO_PROPERTY_MAP_SIZE,
121 MONO_METHOD_SEMA_SIZE,
122 MONO_METHODIMPL_SIZE,
123 MONO_MODULEREF_SIZE, /* 0x1A */
129 MONO_ASSEMBLY_SIZE, /* 0x20 */
130 MONO_ASSEMBLY_PROCESSOR_SIZE,
131 MONO_ASSEMBLYOS_SIZE,
132 MONO_ASSEMBLYREF_SIZE,
133 MONO_ASSEMBLYREFPROC_SIZE,
134 MONO_ASSEMBLYREFOS_SIZE,
138 MONO_NESTED_CLASS_SIZE,
140 MONO_GENERICPARAM_SIZE, /* 0x2A */
141 MONO_METHODSPEC_SIZE,
142 MONO_GENPARCONSTRAINT_SIZE
146 #ifndef DISABLE_REFLECTION_EMIT
147 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
148 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
149 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
150 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
153 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
154 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
155 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
156 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
157 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
158 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
162 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
163 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
164 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
165 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
166 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
167 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
170 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
171 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
172 static gboolean is_sre_array (MonoClass *class);
173 static gboolean is_sre_byref (MonoClass *class);
174 static gboolean is_sre_pointer (MonoClass *class);
175 static gboolean is_sre_type_builder (MonoClass *class);
176 static gboolean is_sre_method_builder (MonoClass *class);
177 static gboolean is_sre_ctor_builder (MonoClass *class);
178 static gboolean is_sre_field_builder (MonoClass *class);
179 static gboolean is_sr_mono_method (MonoClass *class);
180 static gboolean is_sr_mono_cmethod (MonoClass *class);
181 static gboolean is_sr_mono_generic_method (MonoClass *class);
182 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_field (MonoClass *class);
184 static gboolean is_sr_mono_property (MonoClass *class);
185 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
186 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
189 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
190 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
193 static void init_type_builder_generics (MonoObject *type);
195 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
196 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
197 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
198 __type = mono_reflection_type_resolve_user_types (__type); \
199 mono_array_set (arr, MonoReflectionType*, index, __type); \
202 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205 mono_reflection_init (void)
210 sigbuffer_init (SigBuffer *buf, int size)
212 buf->buf = g_malloc (size);
214 buf->end = buf->buf + size;
218 sigbuffer_make_room (SigBuffer *buf, int size)
220 if (buf->end - buf->p < size) {
221 int new_size = buf->end - buf->buf + size + 32;
222 char *p = g_realloc (buf->buf, new_size);
223 size = buf->p - buf->buf;
226 buf->end = buf->buf + new_size;
231 sigbuffer_add_value (SigBuffer *buf, guint32 val)
233 sigbuffer_make_room (buf, 6);
234 mono_metadata_encode_value (val, buf->p, &buf->p);
238 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
240 sigbuffer_make_room (buf, 1);
246 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
248 sigbuffer_make_room (buf, size);
249 memcpy (buf->p, p, size);
254 sigbuffer_free (SigBuffer *buf)
259 #ifndef DISABLE_REFLECTION_EMIT
263 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
267 image_g_malloc (MonoImage *image, guint size)
270 return mono_image_alloc (image, size);
272 return g_malloc (size);
274 #endif /* !DISABLE_REFLECTION_EMIT */
279 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
283 image_g_malloc0 (MonoImage *image, guint size)
286 return mono_image_alloc0 (image, size);
288 return g_malloc0 (size);
291 #ifndef DISABLE_REFLECTION_EMIT
293 image_strdup (MonoImage *image, const char *s)
296 return mono_image_strdup (image, s);
302 #define image_g_new(image,struct_type, n_structs) \
303 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
305 #define image_g_new0(image,struct_type, n_structs) \
306 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
310 alloc_table (MonoDynamicTable *table, guint nrows)
313 g_assert (table->columns);
314 if (nrows + 1 >= table->alloc_rows) {
315 while (nrows + 1 >= table->alloc_rows) {
316 if (table->alloc_rows == 0)
317 table->alloc_rows = 16;
319 table->alloc_rows *= 2;
322 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
327 make_room_in_stream (MonoDynamicStream *stream, int size)
329 if (size <= stream->alloc_size)
332 while (stream->alloc_size <= size) {
333 if (stream->alloc_size < 4096)
334 stream->alloc_size = 4096;
336 stream->alloc_size *= 2;
339 stream->data = g_realloc (stream->data, stream->alloc_size);
343 string_heap_insert (MonoDynamicStream *sh, const char *str)
347 gpointer oldkey, oldval;
349 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
350 return GPOINTER_TO_UINT (oldval);
352 len = strlen (str) + 1;
355 make_room_in_stream (sh, idx + len);
358 * We strdup the string even if we already copy them in sh->data
359 * so that the string pointers in the hash remain valid even if
360 * we need to realloc sh->data. We may want to avoid that later.
362 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
363 memcpy (sh->data + idx, str, len);
369 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
371 char *name = mono_string_to_utf8 (str);
373 idx = string_heap_insert (sh, name);
378 #ifndef DISABLE_REFLECTION_EMIT
380 string_heap_init (MonoDynamicStream *sh)
383 sh->alloc_size = 4096;
384 sh->data = g_malloc (4096);
385 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
386 string_heap_insert (sh, "");
391 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
395 make_room_in_stream (stream, stream->index + len);
396 memcpy (stream->data + stream->index, data, len);
398 stream->index += len;
400 * align index? Not without adding an additional param that controls it since
401 * we may store a blob value in pieces.
407 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
411 make_room_in_stream (stream, stream->index + len);
412 memset (stream->data + stream->index, 0, len);
414 stream->index += len;
419 stream_data_align (MonoDynamicStream *stream)
422 guint32 count = stream->index % 4;
424 /* we assume the stream data will be aligned */
426 mono_image_add_stream_data (stream, buf, 4 - count);
429 #ifndef DISABLE_REFLECTION_EMIT
431 mono_blob_entry_hash (const char* str)
435 len = mono_metadata_decode_blob_size (str, &str);
439 for (str += 1; str < end; str++)
440 h = (h << 5) - h + *str;
448 mono_blob_entry_equal (const char *str1, const char *str2) {
452 len = mono_metadata_decode_blob_size (str1, &end1);
453 len2 = mono_metadata_decode_blob_size (str2, &end2);
456 return memcmp (end1, end2, len) == 0;
460 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
464 gpointer oldkey, oldval;
466 copy = g_malloc (s1+s2);
467 memcpy (copy, b1, s1);
468 memcpy (copy + s1, b2, s2);
469 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471 idx = GPOINTER_TO_UINT (oldval);
473 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
474 mono_image_add_stream_data (&assembly->blob, b2, s2);
475 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
481 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
485 guint32 size = buf->p - buf->buf;
487 g_assert (size <= (buf->end - buf->buf));
488 mono_metadata_encode_value (size, b, &b);
489 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
493 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
494 * dest may be misaligned.
497 swap_with_size (char *dest, const char* val, int len, int nelem) {
498 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
501 for (elem = 0; elem < nelem; ++elem) {
527 g_assert_not_reached ();
533 memcpy (dest, val, len * nelem);
538 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
542 guint32 idx = 0, len;
544 len = str->length * 2;
545 mono_metadata_encode_value (len, b, &b);
546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
548 char *swapped = g_malloc (2 * mono_string_length (str));
549 const char *p = (const char*)mono_string_chars (str);
551 swap_with_size (swapped, p, 2, mono_string_length (str));
552 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
556 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
561 #ifndef DISABLE_REFLECTION_EMIT
563 default_class_from_mono_type (MonoType *type)
565 switch (type->type) {
566 case MONO_TYPE_OBJECT:
567 return mono_defaults.object_class;
569 return mono_defaults.void_class;
570 case MONO_TYPE_BOOLEAN:
571 return mono_defaults.boolean_class;
573 return mono_defaults.char_class;
575 return mono_defaults.sbyte_class;
577 return mono_defaults.byte_class;
579 return mono_defaults.int16_class;
581 return mono_defaults.uint16_class;
583 return mono_defaults.int32_class;
585 return mono_defaults.uint32_class;
587 return mono_defaults.int_class;
589 return mono_defaults.uint_class;
591 return mono_defaults.int64_class;
593 return mono_defaults.uint64_class;
595 return mono_defaults.single_class;
597 return mono_defaults.double_class;
598 case MONO_TYPE_STRING:
599 return mono_defaults.string_class;
601 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
602 g_assert_not_reached ();
610 * mono_class_get_ref_info:
612 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
615 mono_class_get_ref_info (MonoClass *klass)
617 if (klass->ref_info_handle == 0)
620 return mono_gchandle_get_target (klass->ref_info_handle);
624 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
626 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
627 g_assert (klass->ref_info_handle != 0);
631 mono_class_free_ref_info (MonoClass *klass)
633 if (klass->ref_info_handle) {
634 mono_gchandle_free (klass->ref_info_handle);
635 klass->ref_info_handle = 0;
640 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
643 MonoGenericInst *class_inst;
648 class_inst = gclass->context.class_inst;
650 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
651 klass = gclass->container_class;
652 sigbuffer_add_value (buf, klass->byval_arg.type);
653 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
655 sigbuffer_add_value (buf, class_inst->type_argc);
656 for (i = 0; i < class_inst->type_argc; ++i)
657 encode_type (assembly, class_inst->type_argv [i], buf);
662 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
665 g_assert_not_reached ();
670 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
674 case MONO_TYPE_BOOLEAN:
688 case MONO_TYPE_STRING:
689 case MONO_TYPE_OBJECT:
690 case MONO_TYPE_TYPEDBYREF:
691 sigbuffer_add_value (buf, type->type);
694 sigbuffer_add_value (buf, type->type);
695 encode_type (assembly, type->data.type, buf);
697 case MONO_TYPE_SZARRAY:
698 sigbuffer_add_value (buf, type->type);
699 encode_type (assembly, &type->data.klass->byval_arg, buf);
701 case MONO_TYPE_VALUETYPE:
702 case MONO_TYPE_CLASS: {
703 MonoClass *k = mono_class_from_mono_type (type);
705 if (k->generic_container) {
706 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
707 encode_generic_class (assembly, gclass, buf);
710 * Make sure we use the correct type.
712 sigbuffer_add_value (buf, k->byval_arg.type);
714 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
715 * otherwise two typerefs could point to the same type, leading to
716 * verification errors.
718 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
722 case MONO_TYPE_ARRAY:
723 sigbuffer_add_value (buf, type->type);
724 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
725 sigbuffer_add_value (buf, type->data.array->rank);
726 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
727 sigbuffer_add_value (buf, 0);
729 case MONO_TYPE_GENERICINST:
730 encode_generic_class (assembly, type->data.generic_class, buf);
734 sigbuffer_add_value (buf, type->type);
735 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
738 g_error ("need to encode type %x", type->type);
743 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
746 sigbuffer_add_value (buf, MONO_TYPE_VOID);
750 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
754 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
759 for (i = 0; i < mono_array_length (modreq); ++i) {
760 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
761 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
762 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
766 for (i = 0; i < mono_array_length (modopt); ++i) {
767 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
768 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
769 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
774 #ifndef DISABLE_REFLECTION_EMIT
776 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
780 guint32 nparams = sig->param_count;
786 sigbuffer_init (&buf, 32);
788 * FIXME: vararg, explicit_this, differenc call_conv values...
790 idx = sig->call_convention;
792 idx |= 0x20; /* hasthis */
793 if (sig->generic_param_count)
794 idx |= 0x10; /* generic */
795 sigbuffer_add_byte (&buf, idx);
796 if (sig->generic_param_count)
797 sigbuffer_add_value (&buf, sig->generic_param_count);
798 sigbuffer_add_value (&buf, nparams);
799 encode_type (assembly, sig->ret, &buf);
800 for (i = 0; i < nparams; ++i) {
801 if (i == sig->sentinelpos)
802 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
803 encode_type (assembly, sig->params [i], &buf);
805 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
806 sigbuffer_free (&buf);
812 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
815 * FIXME: reuse code from method_encode_signature().
819 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
820 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
821 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
824 sigbuffer_init (&buf, 32);
825 /* LAMESPEC: all the call conv spec is foobared */
826 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
827 if (mb->call_conv & 2)
828 idx |= 0x5; /* vararg */
829 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
830 idx |= 0x20; /* hasthis */
832 idx |= 0x10; /* generic */
833 sigbuffer_add_byte (&buf, idx);
835 sigbuffer_add_value (&buf, ngparams);
836 sigbuffer_add_value (&buf, nparams + notypes);
837 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
838 encode_reflection_type (assembly, mb->rtype, &buf);
839 for (i = 0; i < nparams; ++i) {
840 MonoArray *modreq = NULL;
841 MonoArray *modopt = NULL;
842 MonoReflectionType *pt;
844 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
845 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
846 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
847 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
848 encode_custom_modifiers (assembly, modreq, modopt, &buf);
849 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
850 encode_reflection_type (assembly, pt, &buf);
853 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
854 for (i = 0; i < notypes; ++i) {
855 MonoReflectionType *pt;
857 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
858 encode_reflection_type (assembly, pt, &buf);
861 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
862 sigbuffer_free (&buf);
867 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
869 MonoDynamicTable *table;
871 guint32 idx, sig_idx;
872 guint nl = mono_array_length (ilgen->locals);
876 sigbuffer_init (&buf, 32);
877 sigbuffer_add_value (&buf, 0x07);
878 sigbuffer_add_value (&buf, nl);
879 for (i = 0; i < nl; ++i) {
880 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
883 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
885 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
887 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
888 sigbuffer_free (&buf);
890 if (assembly->standalonesig_cache == NULL)
891 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
892 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
896 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
897 idx = table->next_idx ++;
899 alloc_table (table, table->rows);
900 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
902 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
904 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
910 method_count_clauses (MonoReflectionILGen *ilgen)
912 guint32 num_clauses = 0;
915 MonoILExceptionInfo *ex_info;
916 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
917 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
918 if (ex_info->handlers)
919 num_clauses += mono_array_length (ex_info->handlers);
927 #ifndef DISABLE_REFLECTION_EMIT
928 static MonoExceptionClause*
929 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
931 MonoExceptionClause *clauses;
932 MonoExceptionClause *clause;
933 MonoILExceptionInfo *ex_info;
934 MonoILExceptionBlock *ex_block;
935 guint32 finally_start;
936 int i, j, clause_index;;
938 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
941 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
942 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
943 finally_start = ex_info->start + ex_info->len;
944 if (!ex_info->handlers)
946 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
947 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
948 clause = &(clauses [clause_index]);
950 clause->flags = ex_block->type;
951 clause->try_offset = ex_info->start;
953 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
954 clause->try_len = finally_start - ex_info->start;
956 clause->try_len = ex_info->len;
957 clause->handler_offset = ex_block->start;
958 clause->handler_len = ex_block->len;
959 if (ex_block->extype) {
960 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
963 clause->data.filter_offset = ex_block->filter_offset;
965 clause->data.filter_offset = 0;
967 finally_start = ex_block->start + ex_block->len;
975 #endif /* !DISABLE_REFLECTION_EMIT */
978 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
984 gint32 num_locals = 0;
985 gint32 num_exception = 0;
988 char fat_header [12];
991 guint32 local_sig = 0;
992 guint32 header_size = 12;
995 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
996 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1000 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002 code = mb->ilgen->code;
1003 code_size = mb->ilgen->code_len;
1004 max_stack = mb->ilgen->max_stack;
1005 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1006 if (mb->ilgen->ex_handlers)
1007 num_exception = method_count_clauses (mb->ilgen);
1011 char *name = mono_string_to_utf8 (mb->name);
1012 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1013 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1016 mono_raise_exception (exception);
1019 code_size = mono_array_length (code);
1020 max_stack = 8; /* we probably need to run a verifier on the code... */
1023 stream_data_align (&assembly->code);
1025 /* check for exceptions, maxstack, locals */
1026 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028 if (code_size < 64 && !(code_size & 1)) {
1029 flags = (code_size << 2) | 0x2;
1030 } else if (code_size < 32 && (code_size & 1)) {
1031 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1035 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1036 /* add to the fixup todo list */
1037 if (mb->ilgen && mb->ilgen->num_token_fixups)
1038 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1039 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1040 return assembly->text_rva + idx;
1044 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1046 * FIXME: need to set also the header size in fat_flags.
1047 * (and more sects and init locals flags)
1051 fat_flags |= METHOD_HEADER_MORE_SECTS;
1052 if (mb->init_locals)
1053 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1054 fat_header [0] = fat_flags;
1055 fat_header [1] = (header_size / 4 ) << 4;
1056 short_value = GUINT16_TO_LE (max_stack);
1057 memcpy (fat_header + 2, &short_value, 2);
1058 int_value = GUINT32_TO_LE (code_size);
1059 memcpy (fat_header + 4, &int_value, 4);
1060 int_value = GUINT32_TO_LE (local_sig);
1061 memcpy (fat_header + 8, &int_value, 4);
1062 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1063 /* add to the fixup todo list */
1064 if (mb->ilgen && mb->ilgen->num_token_fixups)
1065 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1067 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1068 if (num_exception) {
1069 unsigned char sheader [4];
1070 MonoILExceptionInfo * ex_info;
1071 MonoILExceptionBlock * ex_block;
1074 stream_data_align (&assembly->code);
1075 /* always use fat format for now */
1076 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1077 num_exception *= 6 * sizeof (guint32);
1078 num_exception += 4; /* include the size of the header */
1079 sheader [1] = num_exception & 0xff;
1080 sheader [2] = (num_exception >> 8) & 0xff;
1081 sheader [3] = (num_exception >> 16) & 0xff;
1082 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1083 /* fat header, so we are already aligned */
1085 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1086 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1087 if (ex_info->handlers) {
1088 int finally_start = ex_info->start + ex_info->len;
1089 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093 val = GUINT32_TO_LE (ex_block->type);
1094 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096 val = GUINT32_TO_LE (ex_info->start);
1097 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1098 /* need fault, too, probably */
1099 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1100 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102 val = GUINT32_TO_LE (ex_info->len);
1103 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1104 /* handler offset */
1105 val = GUINT32_TO_LE (ex_block->start);
1106 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108 val = GUINT32_TO_LE (ex_block->len);
1109 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110 finally_start = ex_block->start + ex_block->len;
1111 if (ex_block->extype) {
1112 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1115 val = ex_block->filter_offset;
1119 val = GUINT32_TO_LE (val);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121 /*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",
1122 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);*/
1125 g_error ("No clauses for ex info block %d", i);
1129 return assembly->text_rva + idx;
1133 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1136 MonoDynamicTable *table;
1139 table = &assembly->tables [table_idx];
1141 g_assert (col < table->columns);
1143 values = table->values + table->columns;
1144 for (i = 1; i <= table->rows; ++i) {
1145 if (values [col] == token)
1147 values += table->columns;
1153 * LOCKING: Acquires the loader lock.
1155 static MonoCustomAttrInfo*
1156 lookup_custom_attr (MonoImage *image, gpointer member)
1158 MonoCustomAttrInfo* res;
1160 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1165 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1171 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1173 /* FIXME: Need to do more checks */
1174 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1175 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1177 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1184 static MonoCustomAttrInfo*
1185 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1187 int i, index, count, not_visible;
1188 MonoCustomAttrInfo *ainfo;
1189 MonoReflectionCustomAttr *cattr;
1193 /* FIXME: check in assembly the Run flag is set */
1195 count = mono_array_length (cattrs);
1197 /* Skip nonpublic attributes since MS.NET seems to do the same */
1198 /* FIXME: This needs to be done more globally */
1200 for (i = 0; i < count; ++i) {
1201 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1202 if (!custom_attr_visible (image, cattr))
1205 count -= not_visible;
1207 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1209 ainfo->image = image;
1210 ainfo->num_attrs = count;
1211 ainfo->cached = alloc_img != NULL;
1213 for (i = 0; i < count; ++i) {
1214 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1215 if (custom_attr_visible (image, cattr)) {
1216 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1217 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1218 ainfo->attrs [index].ctor = cattr->ctor->method;
1219 ainfo->attrs [index].data = saved;
1220 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1228 #ifndef DISABLE_REFLECTION_EMIT
1230 * LOCKING: Acquires the loader lock.
1233 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1235 MonoCustomAttrInfo *ainfo, *tmp;
1237 if (!cattrs || !mono_array_length (cattrs))
1240 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1242 mono_loader_lock ();
1243 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245 mono_custom_attrs_free (tmp);
1246 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1247 mono_loader_unlock ();
1253 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1260 * idx is the table index of the object
1261 * type is one of MONO_CUSTOM_ATTR_*
1264 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1266 MonoDynamicTable *table;
1267 MonoReflectionCustomAttr *cattr;
1269 guint32 count, i, token;
1271 char *p = blob_size;
1273 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1276 count = mono_array_length (cattrs);
1277 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1278 table->rows += count;
1279 alloc_table (table, table->rows);
1280 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1281 idx <<= MONO_CUSTOM_ATTR_BITS;
1283 for (i = 0; i < count; ++i) {
1284 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1285 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1286 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1287 type = mono_metadata_token_index (token);
1288 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1289 switch (mono_metadata_token_table (token)) {
1290 case MONO_TABLE_METHOD:
1291 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293 case MONO_TABLE_MEMBERREF:
1294 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1297 g_warning ("got wrong token in custom attr");
1300 values [MONO_CUSTOM_ATTR_TYPE] = type;
1302 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1303 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1304 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1305 values += MONO_CUSTOM_ATTR_SIZE;
1311 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1313 MonoDynamicTable *table;
1315 guint32 count, i, idx;
1316 MonoReflectionPermissionSet *perm;
1321 count = mono_array_length (permissions);
1322 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1323 table->rows += count;
1324 alloc_table (table, table->rows);
1326 for (i = 0; i < mono_array_length (permissions); ++i) {
1327 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1329 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1331 idx = mono_metadata_token_index (parent_token);
1332 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1333 switch (mono_metadata_token_table (parent_token)) {
1334 case MONO_TABLE_TYPEDEF:
1335 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1337 case MONO_TABLE_METHOD:
1338 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1340 case MONO_TABLE_ASSEMBLY:
1341 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1344 g_assert_not_reached ();
1347 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1348 values [MONO_DECL_SECURITY_PARENT] = idx;
1349 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1356 * Fill in the MethodDef and ParamDef tables for a method.
1357 * This is used for both normal methods and constructors.
1360 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1362 MonoDynamicTable *table;
1366 /* room in this table is already allocated */
1367 table = &assembly->tables [MONO_TABLE_METHOD];
1368 *mb->table_idx = table->next_idx ++;
1369 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1370 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1371 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1372 values [MONO_METHOD_FLAGS] = mb->attrs;
1373 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1374 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1375 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1377 table = &assembly->tables [MONO_TABLE_PARAM];
1378 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1380 mono_image_add_decl_security (assembly,
1381 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1384 MonoDynamicTable *mtable;
1387 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1388 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1391 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1392 if (mono_array_get (mb->pinfo, gpointer, i))
1395 table->rows += count;
1396 alloc_table (table, table->rows);
1397 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1398 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1399 MonoReflectionParamBuilder *pb;
1400 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1401 values [MONO_PARAM_FLAGS] = pb->attrs;
1402 values [MONO_PARAM_SEQUENCE] = i;
1403 if (pb->name != NULL) {
1404 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1406 values [MONO_PARAM_NAME] = 0;
1408 values += MONO_PARAM_SIZE;
1409 if (pb->marshal_info) {
1411 alloc_table (mtable, mtable->rows);
1412 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1413 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1414 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1416 pb->table_idx = table->next_idx++;
1417 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1418 guint32 field_type = 0;
1419 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1421 alloc_table (mtable, mtable->rows);
1422 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1423 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1424 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1425 mvalues [MONO_CONSTANT_TYPE] = field_type;
1426 mvalues [MONO_CONSTANT_PADDING] = 0;
1433 #ifndef DISABLE_REFLECTION_EMIT
1435 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1437 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1439 rmb->ilgen = mb->ilgen;
1440 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1441 rmb->parameters = mb->parameters;
1442 rmb->generic_params = mb->generic_params;
1443 rmb->generic_container = mb->generic_container;
1444 rmb->opt_types = NULL;
1445 rmb->pinfo = mb->pinfo;
1446 rmb->attrs = mb->attrs;
1447 rmb->iattrs = mb->iattrs;
1448 rmb->call_conv = mb->call_conv;
1449 rmb->code = mb->code;
1450 rmb->type = mb->type;
1451 rmb->name = mb->name;
1452 rmb->table_idx = &mb->table_idx;
1453 rmb->init_locals = mb->init_locals;
1454 rmb->skip_visibility = FALSE;
1455 rmb->return_modreq = mb->return_modreq;
1456 rmb->return_modopt = mb->return_modopt;
1457 rmb->param_modreq = mb->param_modreq;
1458 rmb->param_modopt = mb->param_modopt;
1459 rmb->permissions = mb->permissions;
1460 rmb->mhandle = mb->mhandle;
1465 rmb->charset = mb->charset;
1466 rmb->extra_flags = mb->extra_flags;
1467 rmb->native_cc = mb->native_cc;
1468 rmb->dllentry = mb->dllentry;
1474 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1476 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1478 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1480 rmb->ilgen = mb->ilgen;
1481 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1482 rmb->parameters = mb->parameters;
1483 rmb->generic_params = NULL;
1484 rmb->generic_container = NULL;
1485 rmb->opt_types = NULL;
1486 rmb->pinfo = mb->pinfo;
1487 rmb->attrs = mb->attrs;
1488 rmb->iattrs = mb->iattrs;
1489 rmb->call_conv = mb->call_conv;
1491 rmb->type = mb->type;
1492 rmb->name = mono_string_new (mono_domain_get (), name);
1493 rmb->table_idx = &mb->table_idx;
1494 rmb->init_locals = mb->init_locals;
1495 rmb->skip_visibility = FALSE;
1496 rmb->return_modreq = NULL;
1497 rmb->return_modopt = NULL;
1498 rmb->param_modreq = mb->param_modreq;
1499 rmb->param_modopt = mb->param_modopt;
1500 rmb->permissions = mb->permissions;
1501 rmb->mhandle = mb->mhandle;
1507 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1509 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1511 rmb->ilgen = mb->ilgen;
1512 rmb->rtype = mb->rtype;
1513 rmb->parameters = mb->parameters;
1514 rmb->generic_params = NULL;
1515 rmb->generic_container = NULL;
1516 rmb->opt_types = NULL;
1518 rmb->attrs = mb->attrs;
1520 rmb->call_conv = mb->call_conv;
1522 rmb->type = (MonoObject *) mb->owner;
1523 rmb->name = mb->name;
1524 rmb->table_idx = NULL;
1525 rmb->init_locals = mb->init_locals;
1526 rmb->skip_visibility = mb->skip_visibility;
1527 rmb->return_modreq = NULL;
1528 rmb->return_modopt = NULL;
1529 rmb->param_modreq = NULL;
1530 rmb->param_modopt = NULL;
1531 rmb->permissions = NULL;
1532 rmb->mhandle = mb->mhandle;
1539 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1541 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1542 MonoDynamicTable *table;
1546 if (!mb->override_method)
1549 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1551 alloc_table (table, table->rows);
1552 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1553 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1554 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1556 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1557 switch (mono_metadata_token_table (tok)) {
1558 case MONO_TABLE_MEMBERREF:
1559 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1561 case MONO_TABLE_METHOD:
1562 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1565 g_assert_not_reached ();
1567 values [MONO_METHODIMPL_DECLARATION] = tok;
1570 #ifndef DISABLE_REFLECTION_EMIT
1572 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1574 MonoDynamicTable *table;
1576 ReflectionMethodBuilder rmb;
1579 reflection_methodbuilder_from_method_builder (&rmb, mb);
1581 mono_image_basic_method (&rmb, assembly);
1582 mb->table_idx = *rmb.table_idx;
1584 if (mb->dll) { /* It's a P/Invoke method */
1586 /* map CharSet values to on-disk values */
1587 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1588 int extra_flags = mb->extra_flags;
1589 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1591 alloc_table (table, table->rows);
1592 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1594 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1595 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1597 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1599 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1600 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1601 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1602 table = &assembly->tables [MONO_TABLE_MODULEREF];
1604 alloc_table (table, table->rows);
1605 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1606 values [MONO_IMPLMAP_SCOPE] = table->rows;
1610 if (mb->generic_params) {
1611 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1612 table->rows += mono_array_length (mb->generic_params);
1613 alloc_table (table, table->rows);
1614 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1615 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1617 mono_image_get_generic_param_info (
1618 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1625 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1627 ReflectionMethodBuilder rmb;
1629 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1631 mono_image_basic_method (&rmb, assembly);
1632 mb->table_idx = *rmb.table_idx;
1637 type_get_fully_qualified_name (MonoType *type)
1639 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1643 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1647 klass = mono_class_from_mono_type (type);
1649 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1650 ta = klass->image->assembly;
1651 if (ta->dynamic || (ta == ass)) {
1652 if (klass->generic_class || klass->generic_container)
1653 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1654 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1656 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1662 #ifndef DISABLE_REFLECTION_EMIT
1663 /*field_image is the image to which the eventual custom mods have been encoded against*/
1665 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1668 guint32 idx, i, token;
1670 if (!assembly->save)
1673 sigbuffer_init (&buf, 32);
1675 sigbuffer_add_value (&buf, 0x06);
1676 /* encode custom attributes before the type */
1677 if (type->num_mods) {
1678 for (i = 0; i < type->num_mods; ++i) {
1680 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1682 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1684 token = type->modifiers [i].token;
1687 if (type->modifiers [i].required)
1688 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1690 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1692 sigbuffer_add_value (&buf, token);
1695 encode_type (assembly, type, &buf);
1696 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1697 sigbuffer_free (&buf);
1703 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1707 guint32 typespec = 0;
1711 init_type_builder_generics (fb->type);
1713 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1714 class = mono_class_from_mono_type (type);
1716 sigbuffer_init (&buf, 32);
1718 sigbuffer_add_value (&buf, 0x06);
1719 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1720 /* encode custom attributes before the type */
1722 if (class->generic_container)
1723 typespec = create_typespec (assembly, type);
1726 MonoGenericClass *gclass;
1727 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1728 encode_generic_class (assembly, gclass, &buf);
1730 encode_type (assembly, type, &buf);
1732 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1733 sigbuffer_free (&buf);
1738 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1739 char blob_size [64];
1740 char *b = blob_size;
1743 guint32 idx = 0, len = 0, dummy = 0;
1745 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1746 guint32 fpa_double [2];
1751 p = buf = g_malloc (64);
1753 *ret_type = MONO_TYPE_CLASS;
1755 box_val = (char*)&dummy;
1757 box_val = ((char*)val) + sizeof (MonoObject);
1758 *ret_type = val->vtable->klass->byval_arg.type;
1761 switch (*ret_type) {
1762 case MONO_TYPE_BOOLEAN:
1767 case MONO_TYPE_CHAR:
1784 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1785 fpa_p = (guint32*)box_val;
1786 fpa_double [0] = fpa_p [1];
1787 fpa_double [1] = fpa_p [0];
1788 box_val = (char*)fpa_double;
1792 case MONO_TYPE_VALUETYPE: {
1793 MonoClass *klass = val->vtable->klass;
1795 if (klass->enumtype) {
1796 *ret_type = mono_class_enum_basetype (klass)->type;
1798 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1801 g_error ("we can't encode valuetypes, we should have never reached this line");
1804 case MONO_TYPE_CLASS:
1806 case MONO_TYPE_STRING: {
1807 MonoString *str = (MonoString*)val;
1808 /* there is no signature */
1809 len = str->length * 2;
1810 mono_metadata_encode_value (len, b, &b);
1811 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1813 char *swapped = g_malloc (2 * mono_string_length (str));
1814 const char *p = (const char*)mono_string_chars (str);
1816 swap_with_size (swapped, p, 2, mono_string_length (str));
1817 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1821 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1827 case MONO_TYPE_GENERICINST:
1828 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1831 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1834 /* there is no signature */
1835 mono_metadata_encode_value (len, b, &b);
1836 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1837 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1838 swap_with_size (blob_size, box_val, len, 1);
1839 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1841 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1849 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1854 sigbuffer_init (&buf, 32);
1856 sigbuffer_add_value (&buf, minfo->type);
1858 switch (minfo->type) {
1859 case MONO_NATIVE_BYVALTSTR:
1860 case MONO_NATIVE_BYVALARRAY:
1861 sigbuffer_add_value (&buf, minfo->count);
1863 case MONO_NATIVE_LPARRAY:
1864 if (minfo->eltype || minfo->has_size) {
1865 sigbuffer_add_value (&buf, minfo->eltype);
1866 if (minfo->has_size) {
1867 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1868 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1870 /* LAMESPEC: ElemMult is undocumented */
1871 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1875 case MONO_NATIVE_SAFEARRAY:
1877 sigbuffer_add_value (&buf, minfo->eltype);
1879 case MONO_NATIVE_CUSTOM:
1881 str = mono_string_to_utf8 (minfo->guid);
1883 sigbuffer_add_value (&buf, len);
1884 sigbuffer_add_mem (&buf, str, len);
1887 sigbuffer_add_value (&buf, 0);
1889 /* native type name */
1890 sigbuffer_add_value (&buf, 0);
1891 /* custom marshaler type name */
1892 if (minfo->marshaltype || minfo->marshaltyperef) {
1893 if (minfo->marshaltyperef)
1894 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1896 str = mono_string_to_utf8 (minfo->marshaltype);
1898 sigbuffer_add_value (&buf, len);
1899 sigbuffer_add_mem (&buf, str, len);
1902 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1903 sigbuffer_add_value (&buf, 0);
1905 if (minfo->mcookie) {
1906 str = mono_string_to_utf8 (minfo->mcookie);
1908 sigbuffer_add_value (&buf, len);
1909 sigbuffer_add_mem (&buf, str, len);
1912 sigbuffer_add_value (&buf, 0);
1918 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1919 sigbuffer_free (&buf);
1924 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1926 MonoDynamicTable *table;
1929 /* maybe this fixup should be done in the C# code */
1930 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1931 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1932 table = &assembly->tables [MONO_TABLE_FIELD];
1933 fb->table_idx = table->next_idx ++;
1934 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1935 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1936 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1937 values [MONO_FIELD_FLAGS] = fb->attrs;
1938 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1940 if (fb->offset != -1) {
1941 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1943 alloc_table (table, table->rows);
1944 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1945 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1946 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1948 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1949 guint32 field_type = 0;
1950 table = &assembly->tables [MONO_TABLE_CONSTANT];
1952 alloc_table (table, table->rows);
1953 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1954 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1955 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1956 values [MONO_CONSTANT_TYPE] = field_type;
1957 values [MONO_CONSTANT_PADDING] = 0;
1959 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1961 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1963 alloc_table (table, table->rows);
1964 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1965 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1967 * We store it in the code section because it's simpler for now.
1970 if (mono_array_length (fb->rva_data) >= 10)
1971 stream_data_align (&assembly->code);
1972 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1974 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1975 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1977 if (fb->marshal_info) {
1978 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1980 alloc_table (table, table->rows);
1981 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1982 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1983 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1988 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1991 guint32 nparams = 0;
1992 MonoReflectionMethodBuilder *mb = fb->get_method;
1993 MonoReflectionMethodBuilder *smb = fb->set_method;
1996 if (mb && mb->parameters)
1997 nparams = mono_array_length (mb->parameters);
1998 if (!mb && smb && smb->parameters)
1999 nparams = mono_array_length (smb->parameters) - 1;
2000 sigbuffer_init (&buf, 32);
2001 if (fb->call_conv & 0x20)
2002 sigbuffer_add_byte (&buf, 0x28);
2004 sigbuffer_add_byte (&buf, 0x08);
2005 sigbuffer_add_value (&buf, nparams);
2007 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2008 for (i = 0; i < nparams; ++i) {
2009 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2010 encode_reflection_type (assembly, pt, &buf);
2012 } else if (smb && smb->parameters) {
2013 /* the property type is the last param */
2014 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2015 for (i = 0; i < nparams; ++i) {
2016 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2017 encode_reflection_type (assembly, pt, &buf);
2020 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2023 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024 sigbuffer_free (&buf);
2029 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2031 MonoDynamicTable *table;
2033 guint num_methods = 0;
2037 * we need to set things in the following tables:
2038 * PROPERTYMAP (info already filled in _get_type_info ())
2039 * PROPERTY (rows already preallocated in _get_type_info ())
2040 * METHOD (method info already done with the generic method code)
2044 table = &assembly->tables [MONO_TABLE_PROPERTY];
2045 pb->table_idx = table->next_idx ++;
2046 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2047 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2048 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2049 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2051 /* FIXME: we still don't handle 'other' methods */
2052 if (pb->get_method) num_methods ++;
2053 if (pb->set_method) num_methods ++;
2055 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2056 table->rows += num_methods;
2057 alloc_table (table, table->rows);
2059 if (pb->get_method) {
2060 semaidx = table->next_idx ++;
2061 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2062 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2063 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2064 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2066 if (pb->set_method) {
2067 semaidx = table->next_idx ++;
2068 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2069 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2070 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2071 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2073 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2074 guint32 field_type = 0;
2075 table = &assembly->tables [MONO_TABLE_CONSTANT];
2077 alloc_table (table, table->rows);
2078 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2079 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2080 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2081 values [MONO_CONSTANT_TYPE] = field_type;
2082 values [MONO_CONSTANT_PADDING] = 0;
2087 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2089 MonoDynamicTable *table;
2091 guint num_methods = 0;
2095 * we need to set things in the following tables:
2096 * EVENTMAP (info already filled in _get_type_info ())
2097 * EVENT (rows already preallocated in _get_type_info ())
2098 * METHOD (method info already done with the generic method code)
2101 table = &assembly->tables [MONO_TABLE_EVENT];
2102 eb->table_idx = table->next_idx ++;
2103 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2104 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2105 values [MONO_EVENT_FLAGS] = eb->attrs;
2106 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2109 * FIXME: we still don't handle 'other' methods
2111 if (eb->add_method) num_methods ++;
2112 if (eb->remove_method) num_methods ++;
2113 if (eb->raise_method) num_methods ++;
2115 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2116 table->rows += num_methods;
2117 alloc_table (table, table->rows);
2119 if (eb->add_method) {
2120 semaidx = table->next_idx ++;
2121 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2122 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2123 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2124 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2126 if (eb->remove_method) {
2127 semaidx = table->next_idx ++;
2128 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2129 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2130 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2131 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2133 if (eb->raise_method) {
2134 semaidx = table->next_idx ++;
2135 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2136 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2137 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2138 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2143 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2145 MonoDynamicTable *table;
2146 guint32 num_constraints, i;
2150 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2151 num_constraints = gparam->iface_constraints ?
2152 mono_array_length (gparam->iface_constraints) : 0;
2153 table->rows += num_constraints;
2154 if (gparam->base_type)
2156 alloc_table (table, table->rows);
2158 if (gparam->base_type) {
2159 table_idx = table->next_idx ++;
2160 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2162 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2163 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2164 assembly, mono_reflection_type_get_handle (gparam->base_type));
2167 for (i = 0; i < num_constraints; i++) {
2168 MonoReflectionType *constraint = mono_array_get (
2169 gparam->iface_constraints, gpointer, i);
2171 table_idx = table->next_idx ++;
2172 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176 assembly, mono_reflection_type_get_handle (constraint));
2181 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2183 GenericParamTableEntry *entry;
2186 * The GenericParam table must be sorted according to the `owner' field.
2187 * We need to do this sorting prior to writing the GenericParamConstraint
2188 * table, since we have to use the final GenericParam table indices there
2189 * and they must also be sorted.
2192 entry = g_new0 (GenericParamTableEntry, 1);
2193 entry->owner = owner;
2194 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2195 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2196 entry->gparam = gparam;
2198 g_ptr_array_add (assembly->gen_params, entry);
2202 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2204 MonoDynamicTable *table;
2205 MonoGenericParam *param;
2209 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2210 table_idx = table->next_idx ++;
2211 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2213 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2215 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2216 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2217 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2218 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2220 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2222 encode_constraints (entry->gparam, table_idx, assembly);
2226 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2228 MonoDynamicTable *table;
2231 guint32 cols [MONO_ASSEMBLY_SIZE];
2235 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2238 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2239 table = &assembly->tables [MONO_TABLE_MODULEREF];
2240 token = table->next_idx ++;
2242 alloc_table (table, table->rows);
2243 values = table->values + token * MONO_MODULEREF_SIZE;
2244 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2246 token <<= MONO_RESOLTION_SCOPE_BITS;
2247 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2248 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2253 if (image->assembly->dynamic)
2255 memset (cols, 0, sizeof (cols));
2257 /* image->assembly->image is the manifest module */
2258 image = image->assembly->image;
2259 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2262 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2263 token = table->next_idx ++;
2265 alloc_table (table, table->rows);
2266 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2267 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2268 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2269 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2270 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2271 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2272 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2273 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2274 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2276 if (strcmp ("", image->assembly->aname.culture)) {
2277 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2278 image->assembly->aname.culture);
2281 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2282 guchar pubtoken [9];
2284 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2285 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2287 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2289 token <<= MONO_RESOLTION_SCOPE_BITS;
2290 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2291 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2296 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2298 MonoDynamicTable *table;
2303 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2306 sigbuffer_init (&buf, 32);
2307 switch (type->type) {
2308 case MONO_TYPE_FNPTR:
2310 case MONO_TYPE_SZARRAY:
2311 case MONO_TYPE_ARRAY:
2313 case MONO_TYPE_MVAR:
2314 case MONO_TYPE_GENERICINST:
2315 encode_type (assembly, type, &buf);
2317 case MONO_TYPE_CLASS:
2318 case MONO_TYPE_VALUETYPE: {
2319 MonoClass *k = mono_class_from_mono_type (type);
2320 if (!k || !k->generic_container) {
2321 sigbuffer_free (&buf);
2324 encode_type (assembly, type, &buf);
2328 sigbuffer_free (&buf);
2332 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2333 if (assembly->save) {
2334 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2335 alloc_table (table, table->rows + 1);
2336 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2337 values [MONO_TYPESPEC_SIGNATURE] = token;
2339 sigbuffer_free (&buf);
2341 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2342 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2348 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2350 MonoDynamicTable *table;
2352 guint32 token, scope, enclosing;
2355 /* if the type requires a typespec, we must try that first*/
2356 if (try_typespec && (token = create_typespec (assembly, type)))
2358 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2361 klass = mono_class_from_mono_type (type);
2363 klass = mono_class_from_mono_type (type);
2366 * If it's in the same module and not a generic type parameter:
2368 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2369 (type->type != MONO_TYPE_MVAR)) {
2370 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2371 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2372 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2376 if (klass->nested_in) {
2377 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2378 /* get the typeref idx of the enclosing type */
2379 enclosing >>= MONO_TYPEDEFORREF_BITS;
2380 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2382 scope = resolution_scope_from_image (assembly, klass->image);
2384 table = &assembly->tables [MONO_TABLE_TYPEREF];
2385 if (assembly->save) {
2386 alloc_table (table, table->rows + 1);
2387 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2388 values [MONO_TYPEREF_SCOPE] = scope;
2389 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2390 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2392 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2393 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2395 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2400 * Despite the name, we handle also TypeSpec (with the above helper).
2403 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2405 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2408 #ifndef DISABLE_REFLECTION_EMIT
2410 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2412 MonoDynamicTable *table;
2414 guint32 token, pclass;
2416 switch (parent & MONO_TYPEDEFORREF_MASK) {
2417 case MONO_TYPEDEFORREF_TYPEREF:
2418 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2420 case MONO_TYPEDEFORREF_TYPESPEC:
2421 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2423 case MONO_TYPEDEFORREF_TYPEDEF:
2424 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2427 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2430 /* extract the index */
2431 parent >>= MONO_TYPEDEFORREF_BITS;
2433 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2435 if (assembly->save) {
2436 alloc_table (table, table->rows + 1);
2437 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2438 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2439 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2440 values [MONO_MEMBERREF_SIGNATURE] = sig;
2443 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2450 * Insert a memberef row into the metadata: the token that point to the memberref
2451 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2452 * mono_image_get_fieldref_token()).
2453 * The sig param is an index to an already built signature.
2456 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2458 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2459 return mono_image_add_memberef_row (assembly, parent, name, sig);
2464 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2467 MonoMethodSignature *sig;
2469 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2471 if (create_typespec) {
2472 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2477 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478 if (token && !create_typespec)
2481 g_assert (!method->is_inflated);
2484 * A methodref signature can't contain an unmanaged calling convention.
2486 sig = mono_metadata_signature_dup (mono_method_signature (method));
2487 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2488 sig->call_convention = MONO_CALL_DEFAULT;
2489 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2490 method->name, method_encode_signature (assembly, sig));
2492 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2495 if (create_typespec) {
2496 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2497 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2498 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2500 if (assembly->save) {
2503 alloc_table (table, table->rows + 1);
2504 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2505 values [MONO_METHODSPEC_METHOD] = token;
2506 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2509 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2511 /*methodspec and memberef tokens are diferent, */
2512 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2519 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2521 guint32 token, parent, sig;
2522 ReflectionMethodBuilder rmb;
2524 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2526 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2530 name = mono_string_to_utf8 (method->name);
2531 reflection_methodbuilder_from_method_builder (&rmb, method);
2534 * A methodref signature can't contain an unmanaged calling convention.
2535 * Since some flags are encoded as part of call_conv, we need to check against it.
2537 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2538 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2540 sig = method_builder_encode_signature (assembly, &rmb);
2542 if (tb->generic_params)
2543 parent = create_generic_typespec (assembly, tb);
2545 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2547 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2550 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2555 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2556 const gchar *name, guint32 sig)
2558 MonoDynamicTable *table;
2562 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2564 if (assembly->save) {
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2567 values [MONO_MEMBERREF_CLASS] = original;
2568 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2569 values [MONO_MEMBERREF_SIGNATURE] = sig;
2572 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2579 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2583 guint32 nparams = mono_array_length (mb->generic_params);
2586 if (!assembly->save)
2589 sigbuffer_init (&buf, 32);
2591 sigbuffer_add_value (&buf, 0xa);
2592 sigbuffer_add_value (&buf, nparams);
2594 for (i = 0; i < nparams; i++) {
2595 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2596 sigbuffer_add_value (&buf, i);
2599 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2600 sigbuffer_free (&buf);
2605 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2607 MonoDynamicTable *table;
2609 guint32 token, mtoken = 0;
2611 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2615 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2617 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2618 switch (mono_metadata_token_table (mtoken)) {
2619 case MONO_TABLE_MEMBERREF:
2620 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2622 case MONO_TABLE_METHOD:
2623 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2626 g_assert_not_reached ();
2629 if (assembly->save) {
2630 alloc_table (table, table->rows + 1);
2631 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2632 values [MONO_METHODSPEC_METHOD] = mtoken;
2633 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2636 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2639 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2644 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2648 if (mb->generic_params && create_methodspec)
2649 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2651 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2655 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2656 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2661 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2663 guint32 token, parent, sig;
2664 ReflectionMethodBuilder rmb;
2666 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2668 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2672 g_assert (tb->generic_params);
2674 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2676 parent = create_generic_typespec (assembly, tb);
2677 name = mono_string_to_utf8 (rmb.name);
2678 sig = method_builder_encode_signature (assembly, &rmb);
2680 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2683 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2689 is_field_on_inst (MonoClassField *field)
2691 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2695 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2698 get_field_on_inst_generic_type (MonoClassField *field)
2700 MonoClass *class, *gtd;
2701 MonoDynamicGenericClass *dgclass;
2704 g_assert (is_field_on_inst (field));
2706 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2708 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2709 field_index = field - dgclass->fields;
2710 return dgclass->field_generic_types [field_index];
2713 class = field->parent;
2714 gtd = class->generic_class->container_class;
2716 if (field >= class->fields && field - class->fields < class->field.count) {
2717 field_index = field - class->fields;
2718 return gtd->fields [field_index].type;
2721 g_assert_not_reached ();
2725 #ifndef DISABLE_REFLECTION_EMIT
2727 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2733 g_assert (field->parent);
2735 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2739 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2740 int index = field - field->parent->fields;
2741 type = field->parent->generic_class->container_class->fields [index].type;
2743 if (is_field_on_inst (field))
2744 type = get_field_on_inst_generic_type (field);
2748 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2749 mono_field_get_name (field),
2750 fieldref_encode_signature (assembly, field->parent->image, type));
2751 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2756 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2760 MonoGenericClass *gclass;
2761 MonoDynamicGenericClass *dgclass;
2765 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2768 if (is_sre_field_builder (mono_object_class (f->fb))) {
2769 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2770 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2771 klass = mono_class_from_mono_type (type);
2772 gclass = type->data.generic_class;
2773 g_assert (gclass->is_dynamic);
2774 dgclass = (MonoDynamicGenericClass *) gclass;
2776 name = mono_string_to_utf8 (fb->name);
2777 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2778 field_encode_signature (assembly, fb));
2780 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2782 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2784 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785 klass = mono_class_from_mono_type (type);
2787 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2788 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2790 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2791 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2794 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2799 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2803 MonoGenericClass *gclass;
2806 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2808 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2812 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2813 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2814 MonoDynamicGenericClass *dgclass;
2815 ReflectionMethodBuilder rmb;
2818 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819 klass = mono_class_from_mono_type (type);
2821 gclass = type->data.generic_class;
2822 g_assert (gclass->is_dynamic);
2823 dgclass = (MonoDynamicGenericClass *) gclass;
2825 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2827 name = mono_string_to_utf8 (rmb.name);
2829 sig = method_builder_encode_signature (assembly, &rmb);
2831 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2833 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2834 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2836 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2837 klass = mono_class_from_mono_type (type);
2839 sig = method_encode_signature (assembly, mono_method_signature (mm));
2840 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2842 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2843 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2847 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2852 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2855 MonoGenericContext tmp_context;
2856 MonoType **type_argv;
2857 MonoGenericInst *ginst;
2858 MonoMethod *method, *inflated;
2861 init_type_builder_generics ((MonoObject*)m->inst);
2863 method = inflate_method (m->inst, (MonoObject*)m->mb);
2865 klass = method->klass;
2867 if (m->method_args == NULL)
2870 if (method->is_inflated)
2871 method = ((MonoMethodInflated *) method)->declaring;
2873 count = mono_array_length (m->method_args);
2875 type_argv = g_new0 (MonoType *, count);
2876 for (i = 0; i < count; i++) {
2877 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2878 type_argv [i] = mono_reflection_type_get_handle (garg);
2880 ginst = mono_metadata_get_generic_inst (count, type_argv);
2883 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2884 tmp_context.method_inst = ginst;
2886 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2891 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2893 guint32 sig, token = 0;
2897 if (m->method_args) {
2898 MonoMethod *inflated;
2900 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2901 if (create_methodspec)
2902 token = mono_image_get_methodspec_token (assembly, inflated);
2904 token = mono_image_get_inflated_method_token (assembly, inflated);
2908 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2912 if (is_sre_method_builder (mono_object_class (m->mb))) {
2913 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2914 MonoGenericClass *gclass;
2915 ReflectionMethodBuilder rmb;
2918 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2919 klass = mono_class_from_mono_type (type);
2920 gclass = type->data.generic_class;
2921 g_assert (gclass->is_dynamic);
2923 reflection_methodbuilder_from_method_builder (&rmb, mb);
2925 name = mono_string_to_utf8 (rmb.name);
2927 sig = method_builder_encode_signature (assembly, &rmb);
2929 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2931 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2932 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2934 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2935 klass = mono_class_from_mono_type (type);
2937 sig = method_encode_signature (assembly, mono_method_signature (mm));
2938 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2940 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2941 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2944 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2949 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2953 guint32 nparams = context->method_inst->type_argc;
2956 if (!assembly->save)
2959 sigbuffer_init (&buf, 32);
2961 * FIXME: vararg, explicit_this, differenc call_conv values...
2963 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2964 sigbuffer_add_value (&buf, nparams);
2966 for (i = 0; i < nparams; i++)
2967 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2969 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2970 sigbuffer_free (&buf);
2975 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2977 MonoDynamicTable *table;
2979 guint32 token, mtoken = 0, sig;
2980 MonoMethodInflated *imethod;
2981 MonoMethod *declaring;
2983 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2985 g_assert (method->is_inflated);
2986 imethod = (MonoMethodInflated *) method;
2987 declaring = imethod->declaring;
2989 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2990 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2992 if (!mono_method_signature (declaring)->generic_param_count)
2995 switch (mono_metadata_token_table (mtoken)) {
2996 case MONO_TABLE_MEMBERREF:
2997 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2999 case MONO_TABLE_METHOD:
3000 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3003 g_assert_not_reached ();
3006 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3008 if (assembly->save) {
3009 alloc_table (table, table->rows + 1);
3010 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3011 values [MONO_METHODSPEC_METHOD] = mtoken;
3012 values [MONO_METHODSPEC_SIGNATURE] = sig;
3015 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3022 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3024 MonoMethodInflated *imethod;
3027 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3031 g_assert (method->is_inflated);
3032 imethod = (MonoMethodInflated *) method;
3034 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3035 token = method_encode_methodspec (assembly, method);
3037 guint32 sig = method_encode_signature (
3038 assembly, mono_method_signature (imethod->declaring));
3039 token = mono_image_get_memberref_token (
3040 assembly, &method->klass->byval_arg, method->name, sig);
3043 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3048 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3050 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3053 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3054 token = mono_image_get_memberref_token (
3055 assembly, &m->klass->byval_arg, m->name, sig);
3061 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3063 MonoDynamicTable *table;
3072 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3073 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3074 * Because of this, we must not insert it into the `typeref' hash table.
3076 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3077 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3081 sigbuffer_init (&buf, 32);
3083 g_assert (tb->generic_params);
3084 klass = mono_class_from_mono_type (type);
3086 if (tb->generic_container)
3087 mono_reflection_create_generic_class (tb);
3089 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3090 g_assert (klass->generic_container);
3091 sigbuffer_add_value (&buf, klass->byval_arg.type);
3092 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3094 count = mono_array_length (tb->generic_params);
3095 sigbuffer_add_value (&buf, count);
3096 for (i = 0; i < count; i++) {
3097 MonoReflectionGenericParam *gparam;
3099 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3101 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3104 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3106 if (assembly->save) {
3107 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3108 alloc_table (table, table->rows + 1);
3109 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3110 values [MONO_TYPESPEC_SIGNATURE] = token;
3112 sigbuffer_free (&buf);
3114 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3115 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3121 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3124 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3126 int i, count, len, pos;
3131 count += mono_array_length (modreq);
3133 count += mono_array_length (modopt);
3136 return mono_metadata_type_dup (NULL, type);
3138 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3140 memcpy (t, type, MONO_SIZEOF_TYPE);
3142 t->num_mods = count;
3145 for (i = 0; i < mono_array_length (modreq); ++i) {
3146 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3147 t->modifiers [pos].required = 1;
3148 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3153 for (i = 0; i < mono_array_length (modopt); ++i) {
3154 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3155 t->modifiers [pos].required = 0;
3156 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3165 init_type_builder_generics (MonoObject *type)
3167 MonoReflectionTypeBuilder *tb;
3169 if (!is_sre_type_builder(mono_object_class (type)))
3171 tb = (MonoReflectionTypeBuilder *)type;
3173 if (tb && tb->generic_container)
3174 mono_reflection_create_generic_class (tb);
3178 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3180 MonoDynamicTable *table;
3182 MonoType *custom = NULL, *type;
3184 guint32 token, pclass, parent, sig;
3187 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3191 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3192 name = mono_string_to_utf8 (fb->name);
3194 /*FIXME this is one more layer of ugliness due how types are created.*/
3195 init_type_builder_generics (fb->type);
3197 /* fb->type does not include the custom modifiers */
3198 /* FIXME: We should do this in one place when a fieldbuilder is created */
3199 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3200 if (fb->modreq || fb->modopt)
3201 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3203 sig = fieldref_encode_signature (assembly, NULL, type);
3206 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3207 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3209 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3210 parent >>= MONO_TYPEDEFORREF_BITS;
3212 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3214 if (assembly->save) {
3215 alloc_table (table, table->rows + 1);
3216 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3217 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3218 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3219 values [MONO_MEMBERREF_SIGNATURE] = sig;
3222 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3224 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3230 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3237 if (!assembly->save)
3240 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3241 g_assert (helper->type == 2);
3243 if (helper->arguments)
3244 nargs = mono_array_length (helper->arguments);
3248 size = 10 + (nargs * 10);
3250 sigbuffer_init (&buf, 32);
3252 /* Encode calling convention */
3253 /* Change Any to Standard */
3254 if ((helper->call_conv & 0x03) == 0x03)
3255 helper->call_conv = 0x01;
3256 /* explicit_this implies has_this */
3257 if (helper->call_conv & 0x40)
3258 helper->call_conv &= 0x20;
3260 if (helper->call_conv == 0) { /* Unmanaged */
3261 idx = helper->unmanaged_call_conv - 1;
3264 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3265 if (helper->call_conv & 0x02) /* varargs */
3269 sigbuffer_add_byte (&buf, idx);
3270 sigbuffer_add_value (&buf, nargs);
3271 encode_reflection_type (assembly, helper->return_type, &buf);
3272 for (i = 0; i < nargs; ++i) {
3273 MonoArray *modreqs = NULL;
3274 MonoArray *modopts = NULL;
3275 MonoReflectionType *pt;
3277 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3278 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3279 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3280 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3282 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3283 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3284 encode_reflection_type (assembly, pt, &buf);
3286 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287 sigbuffer_free (&buf);
3293 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3296 MonoDynamicTable *table;
3299 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3300 idx = table->next_idx ++;
3302 alloc_table (table, table->rows);
3303 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3305 values [MONO_STAND_ALONE_SIGNATURE] =
3306 mono_reflection_encode_sighelper (assembly, helper);
3312 reflection_cc_to_file (int call_conv) {
3313 switch (call_conv & 0x3) {
3315 case 1: return MONO_CALL_DEFAULT;
3316 case 2: return MONO_CALL_VARARG;
3318 g_assert_not_reached ();
3322 #endif /* !DISABLE_REFLECTION_EMIT */
3326 MonoMethodSignature *sig;
3331 #ifndef DISABLE_REFLECTION_EMIT
3333 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3338 MonoMethodSignature *sig;
3342 name = mono_string_to_utf8 (m->name);
3343 nparams = mono_array_length (m->parameters);
3344 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3346 sig->sentinelpos = -1;
3347 sig->call_convention = reflection_cc_to_file (m->call_conv);
3348 sig->param_count = nparams;
3349 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3350 mtype = mono_reflection_type_get_handle (m->parent);
3351 for (i = 0; i < nparams; ++i)
3352 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3354 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3356 if (strcmp (name, am->name) == 0 &&
3357 mono_metadata_type_equal (am->parent, mtype) &&
3358 mono_metadata_signature_equal (am->sig, sig)) {
3361 m->table_idx = am->token & 0xffffff;
3365 am = g_new0 (ArrayMethod, 1);
3369 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3370 method_encode_signature (assembly, sig));
3371 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3372 m->table_idx = am->token & 0xffffff;
3377 * Insert into the metadata tables all the info about the TypeBuilder tb.
3378 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3381 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3383 MonoDynamicTable *table;
3385 int i, is_object = 0, is_system = 0;
3388 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3389 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3390 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3391 n = mono_string_to_utf8 (tb->name);
3392 if (strcmp (n, "Object") == 0)
3394 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3396 n = mono_string_to_utf8 (tb->nspace);
3397 if (strcmp (n, "System") == 0)
3399 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3401 if (tb->parent && !(is_system && is_object) &&
3402 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3403 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3405 values [MONO_TYPEDEF_EXTENDS] = 0;
3407 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3408 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3411 * if we have explicitlayout or sequentiallayouts, output data in the
3412 * ClassLayout table.
3414 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3415 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3416 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3418 alloc_table (table, table->rows);
3419 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3420 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3421 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3422 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3425 /* handle interfaces */
3426 if (tb->interfaces) {
3427 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3429 table->rows += mono_array_length (tb->interfaces);
3430 alloc_table (table, table->rows);
3431 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3432 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3433 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3434 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3435 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3436 values += MONO_INTERFACEIMPL_SIZE;
3442 table = &assembly->tables [MONO_TABLE_FIELD];
3443 table->rows += tb->num_fields;
3444 alloc_table (table, table->rows);
3445 for (i = 0; i < tb->num_fields; ++i)
3446 mono_image_get_field_info (
3447 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3450 /* handle constructors */
3452 table = &assembly->tables [MONO_TABLE_METHOD];
3453 table->rows += mono_array_length (tb->ctors);
3454 alloc_table (table, table->rows);
3455 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3456 mono_image_get_ctor_info (domain,
3457 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3460 /* handle methods */
3462 table = &assembly->tables [MONO_TABLE_METHOD];
3463 table->rows += tb->num_methods;
3464 alloc_table (table, table->rows);
3465 for (i = 0; i < tb->num_methods; ++i)
3466 mono_image_get_method_info (
3467 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3470 /* Do the same with properties etc.. */
3471 if (tb->events && mono_array_length (tb->events)) {
3472 table = &assembly->tables [MONO_TABLE_EVENT];
3473 table->rows += mono_array_length (tb->events);
3474 alloc_table (table, table->rows);
3475 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3477 alloc_table (table, table->rows);
3478 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3479 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3480 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3481 for (i = 0; i < mono_array_length (tb->events); ++i)
3482 mono_image_get_event_info (
3483 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3485 if (tb->properties && mono_array_length (tb->properties)) {
3486 table = &assembly->tables [MONO_TABLE_PROPERTY];
3487 table->rows += mono_array_length (tb->properties);
3488 alloc_table (table, table->rows);
3489 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3491 alloc_table (table, table->rows);
3492 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3493 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3494 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3495 for (i = 0; i < mono_array_length (tb->properties); ++i)
3496 mono_image_get_property_info (
3497 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3500 /* handle generic parameters */
3501 if (tb->generic_params) {
3502 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3503 table->rows += mono_array_length (tb->generic_params);
3504 alloc_table (table, table->rows);
3505 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3506 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3508 mono_image_get_generic_param_info (
3509 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3513 mono_image_add_decl_security (assembly,
3514 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3517 MonoDynamicTable *ntable;
3519 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520 ntable->rows += mono_array_length (tb->subtypes);
3521 alloc_table (ntable, ntable->rows);
3522 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3524 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3525 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3527 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3528 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3529 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3530 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3531 mono_string_to_utf8 (tb->name), tb->table_idx,
3532 ntable->next_idx, ntable->rows);*/
3533 values += MONO_NESTED_CLASS_SIZE;
3541 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3545 mono_ptr_array_append (*types, type);
3547 if (!type->subtypes)
3550 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3551 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3552 collect_types (types, subtype);
3557 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3559 if ((*type1)->table_idx < (*type2)->table_idx)
3562 if ((*type1)->table_idx > (*type2)->table_idx)
3569 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3574 for (i = 0; i < mono_array_length (pinfo); ++i) {
3575 MonoReflectionParamBuilder *pb;
3576 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3579 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3584 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3587 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3589 for (i = 0; i < tb->num_fields; ++i) {
3590 MonoReflectionFieldBuilder* fb;
3591 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3592 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3596 for (i = 0; i < mono_array_length (tb->events); ++i) {
3597 MonoReflectionEventBuilder* eb;
3598 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3599 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3602 if (tb->properties) {
3603 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3604 MonoReflectionPropertyBuilder* pb;
3605 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3606 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3610 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3611 MonoReflectionCtorBuilder* cb;
3612 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3613 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3614 params_add_cattrs (assembly, cb->pinfo);
3619 for (i = 0; i < tb->num_methods; ++i) {
3620 MonoReflectionMethodBuilder* mb;
3621 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3622 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3623 params_add_cattrs (assembly, mb->pinfo);
3628 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3629 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3634 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3638 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3640 if (moduleb->global_methods) {
3641 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3642 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3643 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3644 params_add_cattrs (assembly, mb->pinfo);
3648 if (moduleb->global_fields) {
3649 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3650 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3651 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3655 if (moduleb->types) {
3656 for (i = 0; i < moduleb->num_types; ++i)
3657 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3662 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3664 MonoDynamicTable *table;
3668 char *b = blob_size;
3671 table = &assembly->tables [MONO_TABLE_FILE];
3673 alloc_table (table, table->rows);
3674 values = table->values + table->next_idx * MONO_FILE_SIZE;
3675 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3676 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3677 if (module->image->dynamic) {
3678 /* This depends on the fact that the main module is emitted last */
3679 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3680 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3683 path = g_strdup (module->image->name);
3685 mono_sha1_get_digest_from_file (path, hash);
3688 mono_metadata_encode_value (20, b, &b);
3689 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3695 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3697 MonoDynamicTable *table;
3700 table = &assembly->tables [MONO_TABLE_MODULE];
3701 mb->table_idx = table->next_idx ++;
3702 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3703 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3706 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3707 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3708 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3709 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3713 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3714 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3716 MonoDynamicTable *table;
3720 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3721 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3724 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3726 alloc_table (table, table->rows);
3727 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3729 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3730 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3731 if (klass->nested_in)
3732 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3734 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3735 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3736 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3738 res = table->next_idx;
3742 /* Emit nested types */
3743 if (klass->ext && klass->ext->nested_classes) {
3746 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3747 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3754 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3755 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3760 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3762 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3764 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3765 parent_index, assembly);
3769 * We need to do this ourselves since klass->nested_classes is not set up.
3772 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3773 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3778 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3779 guint32 module_index, MonoDynamicImage *assembly)
3781 MonoImage *image = module->image;
3785 t = &image->tables [MONO_TABLE_TYPEDEF];
3787 for (i = 0; i < t->rows; ++i) {
3788 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3790 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3791 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3796 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3798 MonoDynamicTable *table;
3800 guint32 scope, scope_idx, impl, current_idx;
3801 gboolean forwarder = TRUE;
3802 gpointer iter = NULL;
3805 if (klass->nested_in) {
3806 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3809 scope = resolution_scope_from_image (assembly, klass->image);
3810 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3811 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3812 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3815 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3818 alloc_table (table, table->rows);
3819 current_idx = table->next_idx;
3820 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3822 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3823 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3824 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3825 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3826 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3830 while ((nested = mono_class_get_nested_types (klass, &iter)))
3831 add_exported_type (assemblyb, assembly, nested, current_idx);
3835 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3840 if (!assemblyb->type_forwarders)
3843 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3844 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3849 type = mono_reflection_type_get_handle (t);
3852 klass = mono_class_from_mono_type (type);
3854 add_exported_type (assemblyb, assembly, klass, 0);
3858 #define align_pointer(base,p)\
3860 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3862 (p) += 4 - (__diff & 3);\
3866 compare_constants (const void *a, const void *b)
3868 const guint32 *a_values = a;
3869 const guint32 *b_values = b;
3870 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3874 compare_semantics (const void *a, const void *b)
3876 const guint32 *a_values = a;
3877 const guint32 *b_values = b;
3878 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3881 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3885 compare_custom_attrs (const void *a, const void *b)
3887 const guint32 *a_values = a;
3888 const guint32 *b_values = b;
3890 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3894 compare_field_marshal (const void *a, const void *b)
3896 const guint32 *a_values = a;
3897 const guint32 *b_values = b;
3899 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3903 compare_nested (const void *a, const void *b)
3905 const guint32 *a_values = a;
3906 const guint32 *b_values = b;
3908 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3912 compare_genericparam (const void *a, const void *b)
3914 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3915 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3917 if ((*b_entry)->owner == (*a_entry)->owner)
3919 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3920 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3922 return (*a_entry)->owner - (*b_entry)->owner;
3926 compare_declsecurity_attrs (const void *a, const void *b)
3928 const guint32 *a_values = a;
3929 const guint32 *b_values = b;
3931 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3935 compare_interface_impl (const void *a, const void *b)
3937 const guint32 *a_values = a;
3938 const guint32 *b_values = b;
3940 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3944 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3948 pad_heap (MonoDynamicStream *sh)
3950 if (sh->index & 3) {
3951 int sz = 4 - (sh->index & 3);
3952 memset (sh->data + sh->index, 0, sz);
3959 MonoDynamicStream *stream;
3963 * build_compressed_metadata() fills in the blob of data that represents the
3964 * raw metadata as it will be saved in the PE file. The five streams are output
3965 * and the metadata tables are comnpressed from the guint32 array representation,
3966 * to the compressed on-disk format.
3969 build_compressed_metadata (MonoDynamicImage *assembly)
3971 MonoDynamicTable *table;
3973 guint64 valid_mask = 0;
3974 guint64 sorted_mask;
3975 guint32 heapt_size = 0;
3976 guint32 meta_size = 256; /* allow for header and other stuff */
3977 guint32 table_offset;
3978 guint32 ntables = 0;
3984 struct StreamDesc stream_desc [5];
3986 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3987 for (i = 0; i < assembly->gen_params->len; i++){
3988 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3989 write_generic_param_entry (assembly, entry);
3992 stream_desc [0].name = "#~";
3993 stream_desc [0].stream = &assembly->tstream;
3994 stream_desc [1].name = "#Strings";
3995 stream_desc [1].stream = &assembly->sheap;
3996 stream_desc [2].name = "#US";
3997 stream_desc [2].stream = &assembly->us;
3998 stream_desc [3].name = "#Blob";
3999 stream_desc [3].stream = &assembly->blob;
4000 stream_desc [4].name = "#GUID";
4001 stream_desc [4].stream = &assembly->guid;
4003 /* tables that are sorted */
4004 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4005 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4006 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4007 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4008 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4009 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4010 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4012 /* Compute table sizes */
4013 /* the MonoImage has already been created in mono_image_basic_init() */
4014 meta = &assembly->image;
4016 /* sizes should be multiple of 4 */
4017 pad_heap (&assembly->blob);
4018 pad_heap (&assembly->guid);
4019 pad_heap (&assembly->sheap);
4020 pad_heap (&assembly->us);
4022 /* Setup the info used by compute_sizes () */
4023 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4024 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4025 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4027 meta_size += assembly->blob.index;
4028 meta_size += assembly->guid.index;
4029 meta_size += assembly->sheap.index;
4030 meta_size += assembly->us.index;
4032 for (i=0; i < MONO_TABLE_NUM; ++i)
4033 meta->tables [i].rows = assembly->tables [i].rows;
4035 for (i = 0; i < MONO_TABLE_NUM; i++){
4036 if (meta->tables [i].rows == 0)
4038 valid_mask |= (guint64)1 << i;
4040 meta->tables [i].row_size = mono_metadata_compute_size (
4041 meta, i, &meta->tables [i].size_bitfield);
4042 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4044 heapt_size += 24; /* #~ header size */
4045 heapt_size += ntables * 4;
4046 /* make multiple of 4 */
4049 meta_size += heapt_size;
4050 meta->raw_metadata = g_malloc0 (meta_size);
4051 p = (unsigned char*)meta->raw_metadata;
4052 /* the metadata signature */
4053 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4054 /* version numbers and 4 bytes reserved */
4055 int16val = (guint16*)p;
4056 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4057 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4059 /* version string */
4060 int32val = (guint32*)p;
4061 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4063 memcpy (p, meta->version, strlen (meta->version));
4064 p += GUINT32_FROM_LE (*int32val);
4065 align_pointer (meta->raw_metadata, p);
4066 int16val = (guint16*)p;
4067 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4068 *int16val = GUINT16_TO_LE (5); /* number of streams */
4072 * write the stream info.
4074 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4075 table_offset += 3; table_offset &= ~3;
4077 assembly->tstream.index = heapt_size;
4078 for (i = 0; i < 5; ++i) {
4079 int32val = (guint32*)p;
4080 stream_desc [i].stream->offset = table_offset;
4081 *int32val++ = GUINT32_TO_LE (table_offset);
4082 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4083 table_offset += GUINT32_FROM_LE (*int32val);
4084 table_offset += 3; table_offset &= ~3;
4086 strcpy ((char*)p, stream_desc [i].name);
4087 p += strlen (stream_desc [i].name) + 1;
4088 align_pointer (meta->raw_metadata, p);
4091 * now copy the data, the table stream header and contents goes first.
4093 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4094 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4095 int32val = (guint32*)p;
4096 *int32val = GUINT32_TO_LE (0); /* reserved */
4099 *p++ = 2; /* version */
4102 if (meta->idx_string_wide)
4104 if (meta->idx_guid_wide)
4106 if (meta->idx_blob_wide)
4109 *p++ = 1; /* reserved */
4110 int64val = (guint64*)p;
4111 *int64val++ = GUINT64_TO_LE (valid_mask);
4112 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4114 int32val = (guint32*)p;
4115 for (i = 0; i < MONO_TABLE_NUM; i++){
4116 if (meta->tables [i].rows == 0)
4118 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4120 p = (unsigned char*)int32val;
4122 /* sort the tables that still need sorting */
4123 table = &assembly->tables [MONO_TABLE_CONSTANT];
4125 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4126 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4128 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4129 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4131 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4132 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4134 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4135 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4137 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4138 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4139 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4141 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4142 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4144 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4146 /* compress the tables */
4147 for (i = 0; i < MONO_TABLE_NUM; i++){
4150 guint32 bitfield = meta->tables [i].size_bitfield;
4151 if (!meta->tables [i].rows)
4153 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4154 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4155 meta->tables [i].base = (char*)p;
4156 for (row = 1; row <= meta->tables [i].rows; ++row) {
4157 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4158 for (col = 0; col < assembly->tables [i].columns; ++col) {
4159 switch (mono_metadata_table_size (bitfield, col)) {
4161 *p++ = values [col];
4164 *p++ = values [col] & 0xff;
4165 *p++ = (values [col] >> 8) & 0xff;
4168 *p++ = values [col] & 0xff;
4169 *p++ = (values [col] >> 8) & 0xff;
4170 *p++ = (values [col] >> 16) & 0xff;
4171 *p++ = (values [col] >> 24) & 0xff;
4174 g_assert_not_reached ();
4178 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4181 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4182 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4183 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4184 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4185 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4187 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4191 * Some tables in metadata need to be sorted according to some criteria, but
4192 * when methods and fields are first created with reflection, they may be assigned a token
4193 * that doesn't correspond to the final token they will get assigned after the sorting.
4194 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4195 * with the reflection objects that represent them. Once all the tables are set up, the
4196 * reflection objects will contains the correct table index. fixup_method() will fixup the
4197 * tokens for the method with ILGenerator @ilgen.
4200 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4202 guint32 code_idx = GPOINTER_TO_UINT (value);
4203 MonoReflectionILTokenInfo *iltoken;
4204 MonoReflectionFieldBuilder *field;
4205 MonoReflectionCtorBuilder *ctor;
4206 MonoReflectionMethodBuilder *method;
4207 MonoReflectionTypeBuilder *tb;
4208 MonoReflectionArrayMethod *am;
4210 unsigned char *target;
4212 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4213 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4214 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4215 switch (target [3]) {
4216 case MONO_TABLE_FIELD:
4217 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4218 field = (MonoReflectionFieldBuilder *)iltoken->member;
4219 idx = field->table_idx;
4220 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4221 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4222 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4224 g_assert_not_reached ();
4227 case MONO_TABLE_METHOD:
4228 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4229 method = (MonoReflectionMethodBuilder *)iltoken->member;
4230 idx = method->table_idx;
4231 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4233 idx = ctor->table_idx;
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4235 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4236 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4237 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4239 g_assert_not_reached ();
4242 case MONO_TABLE_TYPEDEF:
4243 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4244 g_assert_not_reached ();
4245 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4246 idx = tb->table_idx;
4248 case MONO_TABLE_MEMBERREF:
4249 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4250 am = (MonoReflectionArrayMethod*)iltoken->member;
4251 idx = am->table_idx;
4252 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4253 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4254 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4255 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4256 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4257 g_assert (m->klass->generic_class || m->klass->generic_container);
4259 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4261 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4262 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4263 g_assert (is_field_on_inst (f));
4265 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4266 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4268 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4270 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4272 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4275 g_assert_not_reached ();
4278 case MONO_TABLE_METHODSPEC:
4279 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4280 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281 g_assert (mono_method_signature (m)->generic_param_count);
4283 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4285 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4288 g_assert_not_reached ();
4292 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4294 target [0] = idx & 0xff;
4295 target [1] = (idx >> 8) & 0xff;
4296 target [2] = (idx >> 16) & 0xff;
4303 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4304 * value is not known when the table is emitted.
4307 fixup_cattrs (MonoDynamicImage *assembly)
4309 MonoDynamicTable *table;
4311 guint32 type, i, idx, token;
4314 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4316 for (i = 0; i < table->rows; ++i) {
4317 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4319 type = values [MONO_CUSTOM_ATTR_TYPE];
4320 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4321 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4322 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4323 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4326 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4327 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4328 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4329 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4336 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4338 MonoDynamicTable *table;
4341 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4343 alloc_table (table, table->rows);
4344 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4345 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4346 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4347 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4348 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4353 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4355 MonoDynamicTable *table;
4359 char *b = blob_size;
4361 guint32 idx, offset;
4363 if (rsrc->filename) {
4364 name = mono_string_to_utf8 (rsrc->filename);
4365 sname = g_path_get_basename (name);
4367 table = &assembly->tables [MONO_TABLE_FILE];
4369 alloc_table (table, table->rows);
4370 values = table->values + table->next_idx * MONO_FILE_SIZE;
4371 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4372 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4375 mono_sha1_get_digest_from_file (name, hash);
4376 mono_metadata_encode_value (20, b, &b);
4377 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4378 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4380 idx = table->next_idx++;
4382 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4388 data = mono_array_addr (rsrc->data, char, 0);
4389 len = mono_array_length (rsrc->data);
4395 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4396 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4397 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4398 mono_image_add_stream_data (&assembly->resources, data, len);
4402 * The entry should be emitted into the MANIFESTRESOURCE table of
4403 * the main module, but that needs to reference the FILE table
4404 * which isn't emitted yet.
4411 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4415 set_version_from_string (MonoString *version, guint32 *values)
4417 gchar *ver, *p, *str;
4420 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4421 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4422 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4423 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4426 ver = str = mono_string_to_utf8 (version);
4427 for (i = 0; i < 4; ++i) {
4428 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4434 /* handle Revision and Build */
4444 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4448 char *b = blob_size;
4453 len = mono_array_length (pkey);
4454 mono_metadata_encode_value (len, b, &b);
4455 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4456 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4458 assembly->public_key = g_malloc (len);
4459 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4460 assembly->public_key_len = len;
4462 /* Special case: check for ECMA key (16 bytes) */
4463 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4464 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4465 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4466 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4467 /* minimum key size (in 2.0) is 384 bits */
4468 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4470 /* FIXME - verifier */
4471 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4472 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4474 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4480 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4482 MonoDynamicTable *table;
4483 MonoDynamicImage *assembly;
4484 MonoReflectionAssemblyBuilder *assemblyb;
4488 guint32 module_index;
4490 assemblyb = moduleb->assemblyb;
4491 assembly = moduleb->dynamic_image;
4492 domain = mono_object_domain (assemblyb);
4494 /* Emit ASSEMBLY table */
4495 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4496 alloc_table (table, 1);
4497 values = table->values + MONO_ASSEMBLY_SIZE;
4498 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4499 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4500 if (assemblyb->culture) {
4501 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4503 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4505 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4506 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4507 set_version_from_string (assemblyb->version, values);
4509 /* Emit FILE + EXPORTED_TYPE table */
4511 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4513 MonoReflectionModuleBuilder *file_module =
4514 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4515 if (file_module != moduleb) {
4516 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4518 if (file_module->types) {
4519 for (j = 0; j < file_module->num_types; ++j) {
4520 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4521 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4526 if (assemblyb->loaded_modules) {
4527 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4528 MonoReflectionModule *file_module =
4529 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4530 mono_image_fill_file_table (domain, file_module, assembly);
4532 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4535 if (assemblyb->type_forwarders)
4536 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4538 /* Emit MANIFESTRESOURCE table */
4540 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4542 MonoReflectionModuleBuilder *file_module =
4543 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4544 /* The table for the main module is emitted later */
4545 if (file_module != moduleb) {
4547 if (file_module->resources) {
4548 int len = mono_array_length (file_module->resources);
4549 for (j = 0; j < len; ++j) {
4550 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4551 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4558 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4561 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4562 * for the modulebuilder @moduleb.
4563 * At the end of the process, method and field tokens are fixed up and the
4564 * on-disk compressed metadata representation is created.
4567 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4569 MonoDynamicTable *table;
4570 MonoDynamicImage *assembly;
4571 MonoReflectionAssemblyBuilder *assemblyb;
4577 assemblyb = moduleb->assemblyb;
4578 assembly = moduleb->dynamic_image;
4579 domain = mono_object_domain (assemblyb);
4581 if (assembly->text_rva)
4584 assembly->text_rva = START_TEXT_RVA;
4586 if (moduleb->is_main) {
4587 mono_image_emit_manifest (moduleb);
4590 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4591 table->rows = 1; /* .<Module> */
4593 alloc_table (table, table->rows);
4595 * Set the first entry.
4597 values = table->values + table->columns;
4598 values [MONO_TYPEDEF_FLAGS] = 0;
4599 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4600 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4601 values [MONO_TYPEDEF_EXTENDS] = 0;
4602 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4603 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4606 * handle global methods
4607 * FIXME: test what to do when global methods are defined in multiple modules.
4609 if (moduleb->global_methods) {
4610 table = &assembly->tables [MONO_TABLE_METHOD];
4611 table->rows += mono_array_length (moduleb->global_methods);
4612 alloc_table (table, table->rows);
4613 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4614 mono_image_get_method_info (
4615 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4617 if (moduleb->global_fields) {
4618 table = &assembly->tables [MONO_TABLE_FIELD];
4619 table->rows += mono_array_length (moduleb->global_fields);
4620 alloc_table (table, table->rows);
4621 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4622 mono_image_get_field_info (
4623 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4626 table = &assembly->tables [MONO_TABLE_MODULE];
4627 alloc_table (table, 1);
4628 mono_image_fill_module_table (domain, moduleb, assembly);
4630 /* Collect all types into a list sorted by their table_idx */
4631 mono_ptr_array_init (types, moduleb->num_types);
4634 for (i = 0; i < moduleb->num_types; ++i) {
4635 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4636 collect_types (&types, type);
4639 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4640 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4641 table->rows += mono_ptr_array_size (types);
4642 alloc_table (table, table->rows);
4645 * Emit type names + namespaces at one place inside the string heap,
4646 * so load_class_names () needs to touch fewer pages.
4648 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4649 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4650 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4652 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4653 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4654 string_heap_insert_mstring (&assembly->sheap, tb->name);
4657 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4658 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4659 mono_image_get_type_info (domain, type, assembly);
4663 * table->rows is already set above and in mono_image_fill_module_table.
4665 /* add all the custom attributes at the end, once all the indexes are stable */
4666 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4668 /* CAS assembly permissions */
4669 if (assemblyb->permissions_minimum)
4670 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4671 if (assemblyb->permissions_optional)
4672 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4673 if (assemblyb->permissions_refused)
4674 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4676 module_add_cattrs (assembly, moduleb);
4679 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4681 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4682 * the final tokens and don't need another fixup pass. */
4684 if (moduleb->global_methods) {
4685 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4686 MonoReflectionMethodBuilder *mb = mono_array_get (
4687 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4688 mono_image_add_methodimpl (assembly, mb);
4692 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4693 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4694 if (type->methods) {
4695 for (j = 0; j < type->num_methods; ++j) {
4696 MonoReflectionMethodBuilder *mb = mono_array_get (
4697 type->methods, MonoReflectionMethodBuilder*, j);
4699 mono_image_add_methodimpl (assembly, mb);
4704 mono_ptr_array_destroy (types);
4706 fixup_cattrs (assembly);
4709 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4712 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4714 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4717 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4721 guint32 import_lookup_table;
4725 guint32 import_address_table_rva;
4733 #ifndef DISABLE_REFLECTION_EMIT
4736 * mono_image_insert_string:
4737 * @module: module builder object
4740 * Insert @str into the user string stream of @module.
4743 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4745 MonoDynamicImage *assembly;
4750 MONO_ARCH_SAVE_REGS;
4752 if (!module->dynamic_image)
4753 mono_image_module_basic_init (module);
4755 assembly = module->dynamic_image;
4757 if (assembly->save) {
4758 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4759 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4760 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4762 char *swapped = g_malloc (2 * mono_string_length (str));
4763 const char *p = (const char*)mono_string_chars (str);
4765 swap_with_size (swapped, p, 2, mono_string_length (str));
4766 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4770 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4772 mono_image_add_stream_data (&assembly->us, "", 1);
4774 idx = assembly->us.index ++;
4777 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4779 return MONO_TOKEN_STRING | idx;
4783 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4787 MonoMethodSignature *sig;
4789 klass = obj->vtable->klass;
4790 if (strcmp (klass->name, "MonoMethod") == 0) {
4791 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4792 MonoMethodSignature *old;
4793 guint32 sig_token, parent;
4796 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4798 nargs = mono_array_length (opt_param_types);
4799 old = mono_method_signature (method);
4800 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4802 sig->hasthis = old->hasthis;
4803 sig->explicit_this = old->explicit_this;
4804 sig->call_convention = old->call_convention;
4805 sig->generic_param_count = old->generic_param_count;
4806 sig->param_count = old->param_count + nargs;
4807 sig->sentinelpos = old->param_count;
4808 sig->ret = old->ret;
4810 for (i = 0; i < old->param_count; i++)
4811 sig->params [i] = old->params [i];
4813 for (i = 0; i < nargs; i++) {
4814 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4815 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4818 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4819 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4820 parent >>= MONO_TYPEDEFORREF_BITS;
4822 parent <<= MONO_MEMBERREF_PARENT_BITS;
4823 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4825 sig_token = method_encode_signature (assembly, sig);
4826 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4827 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4828 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4829 ReflectionMethodBuilder rmb;
4830 guint32 parent, sig_token;
4831 int nopt_args, nparams, ngparams, i;
4834 reflection_methodbuilder_from_method_builder (&rmb, mb);
4835 rmb.opt_types = opt_param_types;
4836 nopt_args = mono_array_length (opt_param_types);
4838 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4839 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4840 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4842 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4843 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4844 sig->call_convention = rmb.call_conv;
4845 sig->generic_param_count = ngparams;
4846 sig->param_count = nparams + nopt_args;
4847 sig->sentinelpos = nparams;
4848 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4850 for (i = 0; i < nparams; i++) {
4851 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4852 sig->params [i] = mono_reflection_type_get_handle (rt);
4855 for (i = 0; i < nopt_args; i++) {
4856 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4857 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4860 sig_token = method_builder_encode_signature (assembly, &rmb);
4862 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4863 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4865 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4866 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4868 name = mono_string_to_utf8 (rmb.name);
4869 token = mono_image_get_varargs_method_token (
4870 assembly, parent, name, sig_token);
4873 g_error ("requested method token for %s\n", klass->name);
4876 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4877 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4882 * mono_image_create_token:
4883 * @assembly: a dynamic assembly
4885 * @register_token: Whenever to register the token in the assembly->tokens hash.
4887 * Get a token to insert in the IL code stream for the given MemberInfo.
4888 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4889 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4893 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4894 gboolean create_open_instance, gboolean register_token)
4899 klass = obj->vtable->klass;
4901 /* Check for user defined reflection objects */
4902 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4903 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4904 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4906 if (strcmp (klass->name, "MethodBuilder") == 0) {
4907 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4908 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4910 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4911 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4913 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4914 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4915 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4916 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4917 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4919 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4920 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4922 token = mono_image_get_ctorbuilder_token (assembly, mb);
4923 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4924 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4925 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4926 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4927 if (tb->generic_params) {
4928 token = mono_image_get_generic_field_token (assembly, fb);
4930 if ((tb->module->dynamic_image == assembly)) {
4931 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4933 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4936 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4937 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4938 if (create_open_instance && tb->generic_params) {
4940 init_type_builder_generics (obj);
4941 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4942 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4943 token = mono_metadata_token_from_dor (token);
4945 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4947 } else if (strcmp (klass->name, "MonoType") == 0) {
4948 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4949 MonoClass *mc = mono_class_from_mono_type (type);
4950 token = mono_metadata_token_from_dor (
4951 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4952 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4953 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4954 token = mono_metadata_token_from_dor (
4955 mono_image_typedef_or_ref (assembly, type));
4956 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4957 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4958 token = mono_metadata_token_from_dor (
4959 mono_image_typedef_or_ref (assembly, type));
4960 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4961 strcmp (klass->name, "MonoMethod") == 0 ||
4962 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4963 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4964 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4965 if (m->method->is_inflated) {
4966 if (create_open_instance)
4967 token = mono_image_get_methodspec_token (assembly, m->method);
4969 token = mono_image_get_inflated_method_token (assembly, m->method);
4970 } else if ((m->method->klass->image == &assembly->image) &&
4971 !m->method->klass->generic_class) {
4972 static guint32 method_table_idx = 0xffffff;
4973 if (m->method->klass->wastypebuilder) {
4974 /* we use the same token as the one that was assigned
4975 * to the Methodbuilder.
4976 * FIXME: do the equivalent for Fields.
4978 token = m->method->token;
4981 * Each token should have a unique index, but the indexes are
4982 * assigned by managed code, so we don't know about them. An
4983 * easy solution is to count backwards...
4985 method_table_idx --;
4986 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4989 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4991 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4992 } else if (strcmp (klass->name, "MonoField") == 0) {
4993 MonoReflectionField *f = (MonoReflectionField *)obj;
4994 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4995 static guint32 field_table_idx = 0xffffff;
4997 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4999 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5001 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5002 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5003 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5004 token = mono_image_get_array_token (assembly, m);
5005 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5006 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5007 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5008 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5009 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5010 token = mono_metadata_token_from_dor (
5011 mono_image_typedef_or_ref (assembly, type));
5012 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5013 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5014 token = mono_image_get_field_on_inst_token (assembly, f);
5015 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5016 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5017 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5018 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5019 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5020 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5021 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5022 MonoReflectionType *type = (MonoReflectionType *)obj;
5023 token = mono_metadata_token_from_dor (
5024 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5026 g_error ("requested token for %s\n", klass->name);
5030 mono_image_register_token (assembly, token, obj);
5036 * mono_image_register_token:
5038 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5039 * the Module.ResolveXXXToken () methods to work.
5042 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5044 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5046 /* There could be multiple MethodInfo objects with the same token */
5047 //g_assert (prev == obj);
5049 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5053 static MonoDynamicImage*
5054 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5056 static const guchar entrycode [16] = {0xff, 0x25, 0};
5057 MonoDynamicImage *image;
5060 const char *version;
5062 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5063 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5065 version = mono_get_runtime_info ()->runtime_version;
5068 /* The MonoGHashTable's need GC tracking */
5069 image = GC_MALLOC (sizeof (MonoDynamicImage));
5071 image = g_new0 (MonoDynamicImage, 1);
5074 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5076 /*g_print ("created image %p\n", image);*/
5077 /* keep in sync with image.c */
5078 image->image.name = assembly_name;
5079 image->image.assembly_name = image->image.name; /* they may be different */
5080 image->image.module_name = module_name;
5081 image->image.version = g_strdup (version);
5082 image->image.md_version_major = 1;
5083 image->image.md_version_minor = 1;
5084 image->image.dynamic = TRUE;
5086 image->image.references = g_new0 (MonoAssembly*, 1);
5087 image->image.references [0] = NULL;
5089 mono_image_init (&image->image);
5091 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5092 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5093 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5094 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5095 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5096 image->handleref = g_hash_table_new (NULL, NULL);
5097 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5099 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5100 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5101 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5102 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5103 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5104 image->gen_params = g_ptr_array_new ();
5106 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5107 string_heap_init (&image->sheap);
5108 mono_image_add_stream_data (&image->us, "", 1);
5109 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5110 /* import tables... */
5111 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5112 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5113 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5114 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5115 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5116 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5117 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5118 stream_data_align (&image->code);
5120 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5122 for (i=0; i < MONO_TABLE_NUM; ++i) {
5123 image->tables [i].next_idx = 1;
5124 image->tables [i].columns = table_sizes [i];
5127 image->image.assembly = (MonoAssembly*)assembly;
5128 image->run = assembly->run;
5129 image->save = assembly->save;
5130 image->pe_kind = 0x1; /* ILOnly */
5131 image->machine = 0x14c; /* I386 */
5133 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5140 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5146 mono_dynamic_image_free (MonoDynamicImage *image)
5148 MonoDynamicImage *di = image;
5153 mono_g_hash_table_destroy (di->methodspec);
5155 g_hash_table_destroy (di->typespec);
5157 g_hash_table_destroy (di->typeref);
5159 g_hash_table_destroy (di->handleref);
5160 if (di->handleref_managed)
5161 mono_g_hash_table_destroy (di->handleref_managed);
5163 mono_g_hash_table_destroy (di->tokens);
5164 if (di->generic_def_objects)
5165 mono_g_hash_table_destroy (di->generic_def_objects);
5166 if (di->blob_cache) {
5167 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5168 g_hash_table_destroy (di->blob_cache);
5170 if (di->standalonesig_cache)
5171 g_hash_table_destroy (di->standalonesig_cache);
5172 for (list = di->array_methods; list; list = list->next) {
5173 ArrayMethod *am = (ArrayMethod *)list->data;
5178 g_list_free (di->array_methods);
5179 if (di->gen_params) {
5180 for (i = 0; i < di->gen_params->len; i++) {
5181 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5182 mono_gc_deregister_root ((char*) &entry->gparam);
5185 g_ptr_array_free (di->gen_params, TRUE);
5187 if (di->token_fixups)
5188 mono_g_hash_table_destroy (di->token_fixups);
5189 if (di->method_to_table_idx)
5190 g_hash_table_destroy (di->method_to_table_idx);
5191 if (di->field_to_table_idx)
5192 g_hash_table_destroy (di->field_to_table_idx);
5193 if (di->method_aux_hash)
5194 g_hash_table_destroy (di->method_aux_hash);
5195 if (di->vararg_aux_hash)
5196 g_hash_table_destroy (di->vararg_aux_hash);
5197 g_free (di->strong_name);
5198 g_free (di->win32_res);
5200 g_free (di->public_key);
5202 /*g_print ("string heap destroy for image %p\n", di);*/
5203 mono_dynamic_stream_reset (&di->sheap);
5204 mono_dynamic_stream_reset (&di->code);
5205 mono_dynamic_stream_reset (&di->resources);
5206 mono_dynamic_stream_reset (&di->us);
5207 mono_dynamic_stream_reset (&di->blob);
5208 mono_dynamic_stream_reset (&di->tstream);
5209 mono_dynamic_stream_reset (&di->guid);
5210 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5211 g_free (di->tables [i].values);
5215 #ifndef DISABLE_REFLECTION_EMIT
5218 * mono_image_basic_init:
5219 * @assembly: an assembly builder object
5221 * Create the MonoImage that represents the assembly builder and setup some
5222 * of the helper hash table and the basic metadata streams.
5225 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5227 MonoDynamicAssembly *assembly;
5228 MonoDynamicImage *image;
5229 MonoDomain *domain = mono_object_domain (assemblyb);
5231 MONO_ARCH_SAVE_REGS;
5233 if (assemblyb->dynamic_assembly)
5237 /* assembly->assembly.image might be GC allocated */
5238 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5240 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5243 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5245 assembly->assembly.ref_count = 1;
5246 assembly->assembly.dynamic = TRUE;
5247 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5248 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5249 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5250 if (assemblyb->culture)
5251 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5253 assembly->assembly.aname.culture = g_strdup ("");
5255 if (assemblyb->version) {
5256 char *vstr = mono_string_to_utf8 (assemblyb->version);
5257 char **version = g_strsplit (vstr, ".", 4);
5258 char **parts = version;
5259 assembly->assembly.aname.major = atoi (*parts++);
5260 assembly->assembly.aname.minor = atoi (*parts++);
5261 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5262 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5264 g_strfreev (version);
5267 assembly->assembly.aname.major = 0;
5268 assembly->assembly.aname.minor = 0;
5269 assembly->assembly.aname.build = 0;
5270 assembly->assembly.aname.revision = 0;
5273 assembly->run = assemblyb->access != 2;
5274 assembly->save = assemblyb->access != 1;
5275 assembly->domain = domain;
5277 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5278 image->initial_image = TRUE;
5279 assembly->assembly.aname.name = image->image.name;
5280 assembly->assembly.image = &image->image;
5281 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5282 /* -1 to correct for the trailing NULL byte */
5283 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5284 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5286 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5289 mono_domain_assemblies_lock (domain);
5290 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5291 mono_domain_assemblies_unlock (domain);
5293 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5295 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5297 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5300 #endif /* !DISABLE_REFLECTION_EMIT */
5302 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5305 calc_section_size (MonoDynamicImage *assembly)
5309 /* alignment constraints */
5310 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5311 g_assert ((assembly->code.index % 4) == 0);
5312 assembly->meta_size += 3;
5313 assembly->meta_size &= ~3;
5314 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5315 g_assert ((assembly->resources.index % 4) == 0);
5317 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5318 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5321 if (assembly->win32_res) {
5322 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5324 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5325 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5329 assembly->sections [MONO_SECTION_RELOC].size = 12;
5330 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5340 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5344 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5346 ResTreeNode *t1 = (ResTreeNode*)a;
5347 ResTreeNode *t2 = (ResTreeNode*)b;
5349 return t1->id - t2->id;
5353 * resource_tree_create:
5355 * Organize the resources into a resource tree.
5357 static ResTreeNode *
5358 resource_tree_create (MonoArray *win32_resources)
5360 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5364 tree = g_new0 (ResTreeNode, 1);
5366 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5367 MonoReflectionWin32Resource *win32_res =
5368 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5372 /* FIXME: BUG: this stores managed references in unmanaged memory */
5373 lang_node = g_new0 (ResTreeNode, 1);
5374 lang_node->id = win32_res->lang_id;
5375 lang_node->win32_res = win32_res;
5377 /* Create type node if neccesary */
5379 for (l = tree->children; l; l = l->next)
5380 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5381 type_node = (ResTreeNode*)l->data;
5386 type_node = g_new0 (ResTreeNode, 1);
5387 type_node->id = win32_res->res_type;
5390 * The resource types have to be sorted otherwise
5391 * Windows Explorer can't display the version information.
5393 tree->children = g_slist_insert_sorted (tree->children,
5394 type_node, resource_tree_compare_by_id);
5397 /* Create res node if neccesary */
5399 for (l = type_node->children; l; l = l->next)
5400 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5401 res_node = (ResTreeNode*)l->data;
5406 res_node = g_new0 (ResTreeNode, 1);
5407 res_node->id = win32_res->res_id;
5408 type_node->children = g_slist_append (type_node->children, res_node);
5411 res_node->children = g_slist_append (res_node->children, lang_node);
5418 * resource_tree_encode:
5420 * Encode the resource tree into the format used in the PE file.
5423 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5426 MonoPEResourceDir dir;
5427 MonoPEResourceDirEntry dir_entry;
5428 MonoPEResourceDataEntry data_entry;
5430 guint32 res_id_entries;
5433 * For the format of the resource directory, see the article
5434 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5438 memset (&dir, 0, sizeof (dir));
5439 memset (&dir_entry, 0, sizeof (dir_entry));
5440 memset (&data_entry, 0, sizeof (data_entry));
5442 g_assert (sizeof (dir) == 16);
5443 g_assert (sizeof (dir_entry) == 8);
5444 g_assert (sizeof (data_entry) == 16);
5446 node->offset = p - begin;
5448 /* IMAGE_RESOURCE_DIRECTORY */
5449 res_id_entries = g_slist_length (node->children);
5450 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5452 memcpy (p, &dir, sizeof (dir));
5455 /* Reserve space for entries */
5457 p += sizeof (dir_entry) * res_id_entries;
5459 /* Write children */
5460 for (l = node->children; l; l = l->next) {
5461 ResTreeNode *child = (ResTreeNode*)l->data;
5463 if (child->win32_res) {
5466 child->offset = p - begin;
5468 /* IMAGE_RESOURCE_DATA_ENTRY */
5469 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5470 size = mono_array_length (child->win32_res->res_data);
5471 data_entry.rde_size = GUINT32_TO_LE (size);
5473 memcpy (p, &data_entry, sizeof (data_entry));
5474 p += sizeof (data_entry);
5476 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5479 resource_tree_encode (child, begin, p, &p);
5483 /* IMAGE_RESOURCE_ENTRY */
5484 for (l = node->children; l; l = l->next) {
5485 ResTreeNode *child = (ResTreeNode*)l->data;
5487 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5488 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5490 memcpy (entries, &dir_entry, sizeof (dir_entry));
5491 entries += sizeof (dir_entry);
5498 resource_tree_free (ResTreeNode * node)
5501 for (list = node->children; list; list = list->next)
5502 resource_tree_free ((ResTreeNode*)list->data);
5503 g_slist_free(node->children);
5508 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5513 MonoReflectionWin32Resource *win32_res;
5516 if (!assemblyb->win32_resources)
5520 * Resources are stored in a three level tree inside the PE file.
5521 * - level one contains a node for each type of resource
5522 * - level two contains a node for each resource
5523 * - level three contains a node for each instance of a resource for a
5524 * specific language.
5527 tree = resource_tree_create (assemblyb->win32_resources);
5529 /* Estimate the size of the encoded tree */
5531 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5532 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5533 size += mono_array_length (win32_res->res_data);
5535 /* Directory structure */
5536 size += mono_array_length (assemblyb->win32_resources) * 256;
5537 p = buf = g_malloc (size);
5539 resource_tree_encode (tree, p, p, &p);
5541 g_assert (p - buf <= size);
5543 assembly->win32_res = g_malloc (p - buf);
5544 assembly->win32_res_size = p - buf;
5545 memcpy (assembly->win32_res, buf, p - buf);
5548 resource_tree_free (tree);
5552 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5554 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5557 p += sizeof (MonoPEResourceDir);
5558 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5559 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5560 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5561 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5562 fixup_resource_directory (res_section, child, rva);
5564 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5565 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5568 p += sizeof (MonoPEResourceDirEntry);
5573 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5576 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5577 g_error ("WriteFile returned %d\n", GetLastError ());
5581 * mono_image_create_pefile:
5582 * @mb: a module builder object
5584 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5585 * assembly->pefile where it can be easily retrieved later in chunks.
5588 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5590 MonoMSDOSHeader *msdos;
5591 MonoDotNetHeader *header;
5592 MonoSectionTable *section;
5593 MonoCLIHeader *cli_header;
5594 guint32 size, image_size, virtual_base, text_offset;
5595 guint32 header_start, section_start, file_offset, virtual_offset;
5596 MonoDynamicImage *assembly;
5597 MonoReflectionAssemblyBuilder *assemblyb;
5598 MonoDynamicStream pefile_stream = {0};
5599 MonoDynamicStream *pefile = &pefile_stream;
5601 guint32 *rva, value;
5603 static const unsigned char msheader[] = {
5604 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5605 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5608 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5609 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5610 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5611 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5614 assemblyb = mb->assemblyb;
5616 mono_image_basic_init (assemblyb);
5617 assembly = mb->dynamic_image;
5619 assembly->pe_kind = assemblyb->pe_kind;
5620 assembly->machine = assemblyb->machine;
5621 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5622 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5624 mono_image_build_metadata (mb);
5626 if (mb->is_main && assemblyb->resources) {
5627 int len = mono_array_length (assemblyb->resources);
5628 for (i = 0; i < len; ++i)
5629 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5632 if (mb->resources) {
5633 int len = mono_array_length (mb->resources);
5634 for (i = 0; i < len; ++i)
5635 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5638 build_compressed_metadata (assembly);
5641 assembly_add_win32_resources (assembly, assemblyb);
5643 nsections = calc_section_size (assembly);
5645 /* The DOS header and stub */
5646 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5647 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5649 /* the dotnet header */
5650 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5652 /* the section tables */
5653 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5655 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5656 virtual_offset = VIRT_ALIGN;
5659 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5660 if (!assembly->sections [i].size)
5663 file_offset += FILE_ALIGN - 1;
5664 file_offset &= ~(FILE_ALIGN - 1);
5665 virtual_offset += VIRT_ALIGN - 1;
5666 virtual_offset &= ~(VIRT_ALIGN - 1);
5668 assembly->sections [i].offset = file_offset;
5669 assembly->sections [i].rva = virtual_offset;
5671 file_offset += assembly->sections [i].size;
5672 virtual_offset += assembly->sections [i].size;
5673 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5676 file_offset += FILE_ALIGN - 1;
5677 file_offset &= ~(FILE_ALIGN - 1);
5679 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5681 /* back-patch info */
5682 msdos = (MonoMSDOSHeader*)pefile->data;
5683 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5685 header = (MonoDotNetHeader*)(pefile->data + header_start);
5686 header->pesig [0] = 'P';
5687 header->pesig [1] = 'E';
5689 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5690 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5691 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5692 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5693 if (assemblyb->pekind == 1) {
5695 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5698 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5701 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5703 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5704 header->pe.pe_major = 6;
5705 header->pe.pe_minor = 0;
5706 size = assembly->sections [MONO_SECTION_TEXT].size;
5707 size += FILE_ALIGN - 1;
5708 size &= ~(FILE_ALIGN - 1);
5709 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5710 size = assembly->sections [MONO_SECTION_RSRC].size;
5711 size += FILE_ALIGN - 1;
5712 size &= ~(FILE_ALIGN - 1);
5713 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5714 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5715 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5716 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5717 /* pe_rva_entry_point always at the beginning of the text section */
5718 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5720 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5721 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5722 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5723 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5724 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5725 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5726 size = section_start;
5727 size += FILE_ALIGN - 1;
5728 size &= ~(FILE_ALIGN - 1);
5729 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5731 size += VIRT_ALIGN - 1;
5732 size &= ~(VIRT_ALIGN - 1);
5733 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5736 // Translate the PEFileKind value to the value expected by the Windows loader
5742 // PEFileKinds.Dll == 1
5743 // PEFileKinds.ConsoleApplication == 2
5744 // PEFileKinds.WindowApplication == 3
5747 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5748 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5750 if (assemblyb->pekind == 3)
5755 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5757 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5758 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5759 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5760 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5761 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5762 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5764 /* fill data directory entries */
5766 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5767 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5769 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5770 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5772 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5773 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5774 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5775 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5776 /* patch entrypoint name */
5777 if (assemblyb->pekind == 1)
5778 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5780 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5781 /* patch imported function RVA name */
5782 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5783 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5785 /* the import table */
5786 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5787 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5788 /* patch imported dll RVA name and other entries in the dir */
5789 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5790 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5791 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5792 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5793 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5794 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5796 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5797 value = (assembly->text_rva + assembly->imp_names_offset);
5798 *p++ = (value) & 0xff;
5799 *p++ = (value >> 8) & (0xff);
5800 *p++ = (value >> 16) & (0xff);
5801 *p++ = (value >> 24) & (0xff);
5803 /* the CLI header info */
5804 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5805 cli_header->ch_size = GUINT32_FROM_LE (72);
5806 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5807 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5808 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5809 if (assemblyb->entry_point) {
5810 guint32 table_idx = 0;
5811 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5812 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5813 table_idx = methodb->table_idx;
5815 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5817 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5819 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5821 /* The embedded managed resources */
5822 text_offset = assembly->text_rva + assembly->code.index;
5823 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5824 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5825 text_offset += assembly->resources.index;
5826 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5827 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5828 text_offset += assembly->meta_size;
5829 if (assembly->strong_name_size) {
5830 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5831 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5832 text_offset += assembly->strong_name_size;
5835 /* write the section tables and section content */
5836 section = (MonoSectionTable*)(pefile->data + section_start);
5837 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5838 static const char section_names [][7] = {
5839 ".text", ".rsrc", ".reloc"
5841 if (!assembly->sections [i].size)
5843 strcpy (section->st_name, section_names [i]);
5844 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5845 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5846 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5847 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5848 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5849 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5850 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5854 checked_write_file (file, pefile->data, pefile->index);
5856 mono_dynamic_stream_reset (pefile);
5858 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5859 if (!assembly->sections [i].size)
5862 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5863 g_error ("SetFilePointer returned %d\n", GetLastError ());
5866 case MONO_SECTION_TEXT:
5867 /* patch entry point */
5868 p = (guchar*)(assembly->code.data + 2);
5869 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5870 *p++ = (value) & 0xff;
5871 *p++ = (value >> 8) & 0xff;
5872 *p++ = (value >> 16) & 0xff;
5873 *p++ = (value >> 24) & 0xff;
5875 checked_write_file (file, assembly->code.data, assembly->code.index);
5876 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5877 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5878 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5881 g_free (assembly->image.raw_metadata);
5883 case MONO_SECTION_RELOC: {
5887 guint16 type_and_offset;
5891 g_assert (sizeof (reloc) == 12);
5893 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5894 reloc.block_size = GUINT32_FROM_LE (12);
5897 * the entrypoint is always at the start of the text section
5898 * 3 is IMAGE_REL_BASED_HIGHLOW
5899 * 2 is patch_size_rva - text_rva
5901 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5904 checked_write_file (file, &reloc, sizeof (reloc));
5908 case MONO_SECTION_RSRC:
5909 if (assembly->win32_res) {
5911 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5912 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5913 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5917 g_assert_not_reached ();
5921 /* check that the file is properly padded */
5922 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5923 g_error ("SetFilePointer returned %d\n", GetLastError ());
5924 if (! SetEndOfFile (file))
5925 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5927 mono_dynamic_stream_reset (&assembly->code);
5928 mono_dynamic_stream_reset (&assembly->us);
5929 mono_dynamic_stream_reset (&assembly->blob);
5930 mono_dynamic_stream_reset (&assembly->guid);
5931 mono_dynamic_stream_reset (&assembly->sheap);
5933 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5934 g_hash_table_destroy (assembly->blob_cache);
5935 assembly->blob_cache = NULL;
5938 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5941 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5943 g_assert_not_reached ();
5946 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5948 #ifndef DISABLE_REFLECTION_EMIT
5950 MonoReflectionModule *
5951 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5955 MonoImageOpenStatus status;
5956 MonoDynamicAssembly *assembly;
5957 guint32 module_count;
5958 MonoImage **new_modules;
5959 gboolean *new_modules_loaded;
5961 name = mono_string_to_utf8 (fileName);
5963 image = mono_image_open (name, &status);
5966 if (status == MONO_IMAGE_ERROR_ERRNO)
5967 exc = mono_get_exception_file_not_found (fileName);
5969 exc = mono_get_exception_bad_image_format (name);
5971 mono_raise_exception (exc);
5976 assembly = ab->dynamic_assembly;
5977 image->assembly = (MonoAssembly*)assembly;
5979 module_count = image->assembly->image->module_count;
5980 new_modules = g_new0 (MonoImage *, module_count + 1);
5981 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5983 if (image->assembly->image->modules)
5984 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5985 if (image->assembly->image->modules_loaded)
5986 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5987 new_modules [module_count] = image;
5988 new_modules_loaded [module_count] = TRUE;
5989 mono_image_addref (image);
5991 g_free (image->assembly->image->modules);
5992 image->assembly->image->modules = new_modules;
5993 image->assembly->image->modules_loaded = new_modules_loaded;
5994 image->assembly->image->module_count ++;
5996 mono_assembly_load_references (image, &status);
5998 mono_image_close (image);
5999 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6002 return mono_module_get_object (mono_domain_get (), image);
6005 #endif /* DISABLE_REFLECTION_EMIT */
6008 * We need to return always the same object for MethodInfo, FieldInfo etc..
6009 * but we need to consider the reflected type.
6010 * type uses a different hash, since it uses custom hash/equal functions.
6015 MonoClass *refclass;
6019 reflected_equal (gconstpointer a, gconstpointer b) {
6020 const ReflectedEntry *ea = a;
6021 const ReflectedEntry *eb = b;
6023 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6027 reflected_hash (gconstpointer a) {
6028 const ReflectedEntry *ea = a;
6029 return mono_aligned_addr_hash (ea->item);
6032 #define CHECK_OBJECT(t,p,k) \
6038 mono_domain_lock (domain); \
6039 if (!domain->refobject_hash) \
6040 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6041 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6042 mono_domain_unlock (domain); \
6045 mono_domain_unlock (domain); \
6048 #ifdef HAVE_BOEHM_GC
6049 /* ReflectedEntry doesn't need to be GC tracked */
6050 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6051 #define FREE_REFENTRY(entry) g_free ((entry))
6052 #define REFENTRY_REQUIRES_CLEANUP
6054 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6056 #define FREE_REFENTRY(entry)
6059 #define CACHE_OBJECT(t,p,o,k) \
6062 ReflectedEntry pe; \
6064 pe.refclass = (k); \
6065 mono_domain_lock (domain); \
6066 if (!domain->refobject_hash) \
6067 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6068 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6070 ReflectedEntry *e = ALLOC_REFENTRY; \
6072 e->refclass = (k); \
6073 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6076 mono_domain_unlock (domain); \
6081 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6083 mono_domain_lock (domain);
6084 if (domain->refobject_hash) {
6086 gpointer orig_pe, orig_value;
6089 pe.refclass = klass;
6090 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6091 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6092 FREE_REFENTRY (orig_pe);
6095 mono_domain_unlock (domain);
6098 #ifdef REFENTRY_REQUIRES_CLEANUP
6100 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6102 FREE_REFENTRY (key);
6107 mono_reflection_cleanup_domain (MonoDomain *domain)
6109 if (domain->refobject_hash) {
6110 /*let's avoid scanning the whole hashtable if not needed*/
6111 #ifdef REFENTRY_REQUIRES_CLEANUP
6112 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6114 mono_g_hash_table_destroy (domain->refobject_hash);
6115 domain->refobject_hash = NULL;
6119 #ifndef DISABLE_REFLECTION_EMIT
6121 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6123 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6127 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6129 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6133 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6135 MonoDynamicImage *image = moduleb->dynamic_image;
6136 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6140 MonoImage **new_modules;
6142 char *name, *fqname;
6144 * FIXME: we already created an image in mono_image_basic_init (), but
6145 * we don't know which module it belongs to, since that is only
6146 * determined at assembly save time.
6148 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6149 name = mono_string_to_utf8 (ab->name);
6150 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6151 if (!mono_error_ok (&error)) {
6153 mono_error_raise_exception (&error);
6155 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6157 moduleb->module.image = &image->image;
6158 moduleb->dynamic_image = image;
6159 register_module (mono_object_domain (moduleb), moduleb, image);
6161 /* register the module with the assembly */
6162 ass = ab->dynamic_assembly->assembly.image;
6163 module_count = ass->module_count;
6164 new_modules = g_new0 (MonoImage *, module_count + 1);
6167 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6168 new_modules [module_count] = &image->image;
6169 mono_image_addref (&image->image);
6171 g_free (ass->modules);
6172 ass->modules = new_modules;
6173 ass->module_count ++;
6178 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6180 MonoDynamicImage *image = moduleb->dynamic_image;
6182 g_assert (type->type);
6183 image->wrappers_type = mono_class_from_mono_type (type->type);
6189 * mono_assembly_get_object:
6190 * @domain: an app domain
6191 * @assembly: an assembly
6193 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6195 MonoReflectionAssembly*
6196 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6198 static MonoClass *assembly_type;
6199 MonoReflectionAssembly *res;
6201 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6202 if (!assembly_type) {
6203 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6205 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6207 assembly_type = class;
6209 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6210 res->assembly = assembly;
6212 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6217 MonoReflectionModule*
6218 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6220 static MonoClass *module_type;
6221 MonoReflectionModule *res;
6224 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6226 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6228 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6230 module_type = class;
6232 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6235 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6237 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6238 basename = g_path_get_basename (image->name);
6239 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6240 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6244 if (image->assembly->image == image) {
6245 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6249 if (image->assembly->image->modules) {
6250 for (i = 0; i < image->assembly->image->module_count; i++) {
6251 if (image->assembly->image->modules [i] == image)
6252 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6254 g_assert (res->token);
6258 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6261 MonoReflectionModule*
6262 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6264 static MonoClass *module_type;
6265 MonoReflectionModule *res;
6266 MonoTableInfo *table;
6267 guint32 cols [MONO_FILE_SIZE];
6269 guint32 i, name_idx;
6273 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6275 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6277 module_type = class;
6279 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6281 table = &image->tables [MONO_TABLE_FILE];
6282 g_assert (table_index < table->rows);
6283 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6286 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6287 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6289 /* Check whenever the row has a corresponding row in the moduleref table */
6290 table = &image->tables [MONO_TABLE_MODULEREF];
6291 for (i = 0; i < table->rows; ++i) {
6292 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6293 val = mono_metadata_string_heap (image, name_idx);
6294 if (strcmp (val, name) == 0)
6295 res->image = image->modules [i];
6298 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6299 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6300 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6301 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6302 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6308 verify_safe_for_managed_space (MonoType *type)
6310 switch (type->type) {
6312 case MONO_TYPE_ARRAY:
6313 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6315 return verify_safe_for_managed_space (type->data.type);
6316 case MONO_TYPE_SZARRAY:
6317 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6318 case MONO_TYPE_GENERICINST: {
6319 MonoGenericInst *inst = type->data.generic_class->inst;
6323 for (i = 0; i < inst->type_argc; ++i)
6324 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6330 case MONO_TYPE_MVAR:
6337 mono_type_normalize (MonoType *type)
6340 MonoGenericClass *gclass;
6341 MonoGenericInst *ginst;
6343 MonoGenericContainer *gcontainer;
6344 MonoType **argv = NULL;
6345 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6347 if (type->type != MONO_TYPE_GENERICINST)
6350 gclass = type->data.generic_class;
6351 ginst = gclass->context.class_inst;
6352 if (!ginst->is_open)
6355 gtd = gclass->container_class;
6356 gcontainer = gtd->generic_container;
6357 argv = g_newa (MonoType*, ginst->type_argc);
6359 for (i = 0; i < ginst->type_argc; ++i) {
6360 MonoType *t = ginst->type_argv [i], *norm;
6361 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6362 is_denorm_gtd = FALSE;
6363 norm = mono_type_normalize (t);
6366 requires_rebind = TRUE;
6370 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6372 if (requires_rebind) {
6373 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6374 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6380 * mono_type_get_object:
6381 * @domain: an app domain
6384 * Return an System.MonoType object representing the type @type.
6387 mono_type_get_object (MonoDomain *domain, MonoType *type)
6389 MonoType *norm_type;
6390 MonoReflectionType *res;
6391 MonoClass *klass = mono_class_from_mono_type (type);
6393 /*we must avoid using @type as it might have come
6394 * from a mono_metadata_type_dup and the caller
6395 * expects that is can be freed.
6396 * Using the right type from
6398 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6400 /* void is very common */
6401 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6402 return (MonoReflectionType*)domain->typeof_void;
6405 * If the vtable of the given class was already created, we can use
6406 * the MonoType from there and avoid all locking and hash table lookups.
6408 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6409 * that the resulting object is different.
6411 if (type == &klass->byval_arg && !klass->image->dynamic) {
6412 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6413 if (vtable && vtable->type)
6414 return vtable->type;
6417 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6418 mono_domain_lock (domain);
6419 if (!domain->type_hash)
6420 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6421 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6422 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6423 mono_domain_unlock (domain);
6424 mono_loader_unlock ();
6428 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6429 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6430 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6431 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6432 * artifact of how generics are encoded and should be transparent to managed code so we
6433 * need to weed out this diference when retrieving managed System.Type objects.
6435 norm_type = mono_type_normalize (type);
6436 if (norm_type != type) {
6437 res = mono_type_get_object (domain, norm_type);
6438 mono_g_hash_table_insert (domain->type_hash, type, res);
6439 mono_domain_unlock (domain);
6440 mono_loader_unlock ();
6444 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6445 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6448 if (!verify_safe_for_managed_space (type)) {
6449 mono_domain_unlock (domain);
6450 mono_loader_unlock ();
6451 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6454 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6455 gboolean is_type_done = TRUE;
6456 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6457 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6458 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6460 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6461 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6463 if (gparam->owner && gparam->owner->is_method) {
6464 MonoMethod *method = gparam->owner->owner.method;
6465 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6466 is_type_done = FALSE;
6467 } else if (gparam->owner && !gparam->owner->is_method) {
6468 MonoClass *klass = gparam->owner->owner.klass;
6469 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6470 is_type_done = FALSE;
6474 /* g_assert_not_reached (); */
6475 /* should this be considered an error condition? */
6476 if (is_type_done && !type->byref) {
6477 mono_domain_unlock (domain);
6478 mono_loader_unlock ();
6479 return mono_class_get_ref_info (klass);
6482 /* This is stored in vtables/JITted code so it has to be pinned */
6483 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6485 mono_g_hash_table_insert (domain->type_hash, type, res);
6487 if (type->type == MONO_TYPE_VOID)
6488 domain->typeof_void = (MonoObject*)res;
6490 mono_domain_unlock (domain);
6491 mono_loader_unlock ();
6496 * mono_method_get_object:
6497 * @domain: an app domain
6499 * @refclass: the reflected type (can be NULL)
6501 * Return an System.Reflection.MonoMethod object representing the method @method.
6503 MonoReflectionMethod*
6504 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6507 * We use the same C representation for methods and constructors, but the type
6508 * name in C# is different.
6510 static MonoClass *System_Reflection_MonoMethod = NULL;
6511 static MonoClass *System_Reflection_MonoCMethod = NULL;
6512 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6513 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6515 MonoReflectionMethod *ret;
6517 if (method->is_inflated) {
6518 MonoReflectionGenericMethod *gret;
6520 refclass = method->klass;
6521 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6522 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6523 if (!System_Reflection_MonoGenericCMethod)
6524 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6525 klass = System_Reflection_MonoGenericCMethod;
6527 if (!System_Reflection_MonoGenericMethod)
6528 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6529 klass = System_Reflection_MonoGenericMethod;
6531 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6532 gret->method.method = method;
6533 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6534 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6535 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6539 refclass = method->klass;
6541 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6542 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6543 if (!System_Reflection_MonoCMethod)
6544 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6545 klass = System_Reflection_MonoCMethod;
6548 if (!System_Reflection_MonoMethod)
6549 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6550 klass = System_Reflection_MonoMethod;
6552 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6553 ret->method = method;
6554 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6555 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6559 * mono_method_clear_object:
6561 * Clear the cached reflection objects for the dynamic method METHOD.
6564 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6567 g_assert (method->dynamic);
6569 klass = method->klass;
6571 clear_cached_object (domain, method, klass);
6572 klass = klass->parent;
6574 /* Added by mono_param_get_objects () */
6575 clear_cached_object (domain, &(method->signature), NULL);
6576 klass = method->klass;
6578 clear_cached_object (domain, &(method->signature), klass);
6579 klass = klass->parent;
6584 * mono_field_get_object:
6585 * @domain: an app domain
6589 * Return an System.Reflection.MonoField object representing the field @field
6592 MonoReflectionField*
6593 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6595 MonoReflectionField *res;
6596 static MonoClass *monofield_klass;
6598 CHECK_OBJECT (MonoReflectionField *, field, klass);
6599 if (!monofield_klass)
6600 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6601 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6604 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6606 if (is_field_on_inst (field)) {
6607 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6608 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6611 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6612 res->attrs = mono_field_get_flags (field);
6614 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6618 * mono_property_get_object:
6619 * @domain: an app domain
6621 * @property: a property
6623 * Return an System.Reflection.MonoProperty object representing the property @property
6626 MonoReflectionProperty*
6627 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6629 MonoReflectionProperty *res;
6630 static MonoClass *monoproperty_klass;
6632 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6633 if (!monoproperty_klass)
6634 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6635 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6637 res->property = property;
6638 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6642 * mono_event_get_object:
6643 * @domain: an app domain
6647 * Return an System.Reflection.MonoEvent object representing the event @event
6650 MonoReflectionEvent*
6651 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6653 MonoReflectionEvent *res;
6654 MonoReflectionMonoEvent *mono_event;
6655 static MonoClass *monoevent_klass;
6657 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6658 if (!monoevent_klass)
6659 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6660 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6661 mono_event->klass = klass;
6662 mono_event->event = event;
6663 res = (MonoReflectionEvent*)mono_event;
6664 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6668 * mono_get_reflection_missing_object:
6669 * @domain: Domain where the object lives
6671 * Returns the System.Reflection.Missing.Value singleton object
6672 * (of type System.Reflection.Missing).
6674 * Used as the value for ParameterInfo.DefaultValue when Optional
6678 mono_get_reflection_missing_object (MonoDomain *domain)
6681 static MonoClassField *missing_value_field = NULL;
6683 if (!missing_value_field) {
6684 MonoClass *missing_klass;
6685 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6686 mono_class_init (missing_klass);
6687 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6688 g_assert (missing_value_field);
6690 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6696 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6699 *dbnull = mono_get_dbnull_object (domain);
6704 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6706 if (!*reflection_missing)
6707 *reflection_missing = mono_get_reflection_missing_object (domain);
6708 return *reflection_missing;
6712 * mono_param_get_objects:
6713 * @domain: an app domain
6716 * Return an System.Reflection.ParameterInfo array object representing the parameters
6717 * in the method @method.
6720 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6722 static MonoClass *System_Reflection_ParameterInfo;
6723 static MonoClass *System_Reflection_ParameterInfo_array;
6725 MonoArray *res = NULL;
6726 MonoReflectionMethod *member = NULL;
6727 MonoReflectionParameter *param = NULL;
6728 char **names, **blobs = NULL;
6729 guint32 *types = NULL;
6730 MonoType *type = NULL;
6731 MonoObject *dbnull = NULL;
6732 MonoObject *missing = NULL;
6733 MonoMarshalSpec **mspecs;
6734 MonoMethodSignature *sig;
6735 MonoVTable *pinfo_vtable;
6738 if (!System_Reflection_ParameterInfo_array) {
6741 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6742 mono_memory_barrier ();
6743 System_Reflection_ParameterInfo = klass;
6745 klass = mono_array_class_get (klass, 1);
6746 mono_memory_barrier ();
6747 System_Reflection_ParameterInfo_array = klass;
6750 sig = mono_method_signature_checked (method, &error);
6751 if (!mono_error_ok (&error))
6752 mono_error_raise_exception (&error);
6754 if (!sig->param_count)
6755 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6757 /* Note: the cache is based on the address of the signature into the method
6758 * since we already cache MethodInfos with the method as keys.
6760 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6762 member = mono_method_get_object (domain, method, refclass);
6763 names = g_new (char *, sig->param_count);
6764 mono_method_get_param_names (method, (const char **) names);
6766 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6767 mono_method_get_marshal_info (method, mspecs);
6769 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6770 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6771 for (i = 0; i < sig->param_count; ++i) {
6772 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6773 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6774 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6775 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6776 param->PositionImpl = i;
6777 param->AttrsImpl = sig->params [i]->attrs;
6779 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6780 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6781 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6783 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6787 blobs = g_new0 (char *, sig->param_count);
6788 types = g_new0 (guint32, sig->param_count);
6789 get_default_param_value_blobs (method, blobs, types);
6792 /* Build MonoType for the type from the Constant Table */
6794 type = g_new0 (MonoType, 1);
6795 type->type = types [i];
6796 type->data.klass = NULL;
6797 if (types [i] == MONO_TYPE_CLASS)
6798 type->data.klass = mono_defaults.object_class;
6799 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6800 /* For enums, types [i] contains the base type */
6802 type->type = MONO_TYPE_VALUETYPE;
6803 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6805 type->data.klass = mono_class_from_mono_type (type);
6807 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6809 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6810 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6811 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6812 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6814 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6820 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6822 mono_array_setref (res, i, param);
6829 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6831 mono_metadata_free_marshal_spec (mspecs [i]);
6834 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6838 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6840 return mono_param_get_objects_internal (domain, method, NULL);
6844 * mono_method_body_get_object:
6845 * @domain: an app domain
6848 * Return an System.Reflection.MethodBody object representing the method @method.
6850 MonoReflectionMethodBody*
6851 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6853 static MonoClass *System_Reflection_MethodBody = NULL;
6854 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6855 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6856 MonoReflectionMethodBody *ret;
6857 MonoMethodHeader *header;
6859 guint32 method_rva, local_var_sig_token;
6861 unsigned char format, flags;
6864 /* for compatibility with .net */
6865 if (method->dynamic)
6866 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6868 if (!System_Reflection_MethodBody)
6869 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6870 if (!System_Reflection_LocalVariableInfo)
6871 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6872 if (!System_Reflection_ExceptionHandlingClause)
6873 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6875 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6877 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6878 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6879 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6880 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6883 image = method->klass->image;
6884 header = mono_method_get_header (method);
6886 if (!image->dynamic) {
6887 /* Obtain local vars signature token */
6888 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6889 ptr = mono_image_rva_map (image, method_rva);
6890 flags = *(const unsigned char *) ptr;
6891 format = flags & METHOD_HEADER_FORMAT_MASK;
6893 case METHOD_HEADER_TINY_FORMAT:
6894 local_var_sig_token = 0;
6896 case METHOD_HEADER_FAT_FORMAT:
6900 local_var_sig_token = read32 (ptr);
6903 g_assert_not_reached ();
6906 local_var_sig_token = 0; //FIXME
6908 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6910 ret->init_locals = header->init_locals;
6911 ret->max_stack = header->max_stack;
6912 ret->local_var_sig_token = local_var_sig_token;
6913 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6914 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6917 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6918 for (i = 0; i < header->num_locals; ++i) {
6919 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6920 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6921 info->is_pinned = header->locals [i]->pinned;
6922 info->local_index = i;
6923 mono_array_setref (ret->locals, i, info);
6927 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6928 for (i = 0; i < header->num_clauses; ++i) {
6929 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6930 MonoExceptionClause *clause = &header->clauses [i];
6932 info->flags = clause->flags;
6933 info->try_offset = clause->try_offset;
6934 info->try_length = clause->try_len;
6935 info->handler_offset = clause->handler_offset;
6936 info->handler_length = clause->handler_len;
6937 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6938 info->filter_offset = clause->data.filter_offset;
6939 else if (clause->data.catch_class)
6940 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6942 mono_array_setref (ret->clauses, i, info);
6945 mono_metadata_free_mh (header);
6946 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6951 * mono_get_dbnull_object:
6952 * @domain: Domain where the object lives
6954 * Returns the System.DBNull.Value singleton object
6956 * Used as the value for ParameterInfo.DefaultValue
6959 mono_get_dbnull_object (MonoDomain *domain)
6962 static MonoClassField *dbnull_value_field = NULL;
6964 if (!dbnull_value_field) {
6965 MonoClass *dbnull_klass;
6966 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6967 mono_class_init (dbnull_klass);
6968 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6969 g_assert (dbnull_value_field);
6971 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6977 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6979 guint32 param_index, i, lastp, crow = 0;
6980 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6983 MonoClass *klass = method->klass;
6984 MonoImage *image = klass->image;
6985 MonoMethodSignature *methodsig = mono_method_signature (method);
6987 MonoTableInfo *constt;
6988 MonoTableInfo *methodt;
6989 MonoTableInfo *paramt;
6991 if (!methodsig->param_count)
6994 mono_class_init (klass);
6996 if (klass->image->dynamic) {
6997 MonoReflectionMethodAux *aux;
6998 if (method->is_inflated)
6999 method = ((MonoMethodInflated*)method)->declaring;
7000 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7001 if (aux && aux->param_defaults) {
7002 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7003 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7008 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7009 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7010 constt = &image->tables [MONO_TABLE_CONSTANT];
7012 idx = mono_method_get_index (method) - 1;
7013 g_assert (idx != -1);
7015 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7016 if (idx + 1 < methodt->rows)
7017 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7019 lastp = paramt->rows + 1;
7021 for (i = param_index; i < lastp; ++i) {
7024 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7025 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7027 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7030 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7035 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7036 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7037 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7044 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7049 MonoType *basetype = type;
7054 klass = mono_class_from_mono_type (type);
7055 if (klass->valuetype) {
7056 object = mono_object_new (domain, klass);
7057 retval = ((gchar *) object + sizeof (MonoObject));
7058 if (klass->enumtype)
7059 basetype = mono_class_enum_basetype (klass);
7064 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7071 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7074 gboolean quoted = FALSE;
7076 memset (assembly, 0, sizeof (MonoAssemblyName));
7077 assembly->culture = "";
7078 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7085 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7096 /* Remove trailing whitespace */
7098 while (*s && g_ascii_isspace (*s))
7101 while (g_ascii_isspace (*p))
7104 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7106 assembly->major = strtoul (p, &s, 10);
7107 if (s == p || *s != '.')
7110 assembly->minor = strtoul (p, &s, 10);
7111 if (s == p || *s != '.')
7114 assembly->build = strtoul (p, &s, 10);
7115 if (s == p || *s != '.')
7118 assembly->revision = strtoul (p, &s, 10);
7122 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7124 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7125 assembly->culture = "";
7128 assembly->culture = p;
7129 while (*p && *p != ',') {
7133 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7135 if (strncmp (p, "null", 4) == 0) {
7140 while (*p && *p != ',') {
7143 len = (p - start + 1);
7144 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7145 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7146 g_strlcpy ((char*)assembly->public_key_token, start, len);
7149 while (*p && *p != ',')
7153 while (g_ascii_isspace (*p) || *p == ',') {
7167 * mono_reflection_parse_type:
7170 * Parse a type name as accepted by the GetType () method and output the info
7171 * extracted in the info structure.
7172 * the name param will be mangled, so, make a copy before passing it to this function.
7173 * The fields in info will be valid until the memory pointed to by name is valid.
7175 * See also mono_type_get_name () below.
7177 * Returns: 0 on parse error.
7180 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7181 MonoTypeNameParse *info)
7183 char *start, *p, *w, *temp, *last_point, *startn;
7184 int in_modifiers = 0;
7185 int isbyref = 0, rank, arity = 0, i;
7187 start = p = w = name;
7189 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7190 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7191 info->name = info->name_space = NULL;
7192 info->nested = NULL;
7193 info->modifiers = NULL;
7194 info->type_arguments = NULL;
7196 /* last_point separates the namespace from the name */
7199 while (*p == ' ') p++, start++, w++, name++;
7204 *p = 0; /* NULL terminate the name */
7206 info->nested = g_list_append (info->nested, startn);
7207 /* we have parsed the nesting namespace + name */
7211 info->name_space = start;
7213 info->name = last_point + 1;
7215 info->name_space = (char *)"";
7234 i = strtol (p, &temp, 10);
7251 info->name_space = start;
7253 info->name = last_point + 1;
7255 info->name_space = (char *)"";
7262 if (isbyref) /* only one level allowed by the spec */
7265 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7269 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7275 info->type_arguments = g_ptr_array_new ();
7276 for (i = 0; i < arity; i++) {
7277 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7278 gboolean fqname = FALSE;
7280 g_ptr_array_add (info->type_arguments, subinfo);
7287 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7290 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7291 if (fqname && (*p != ']')) {
7299 while (*p && (*p != ']'))
7307 if (g_ascii_isspace (*aname)) {
7314 !assembly_name_to_aname (&subinfo->assembly, aname))
7316 } else if (fqname && (*p == ']')) {
7320 if (i + 1 < arity) {
7340 else if (*p == '*') /* '*' means unknown lower bound */
7341 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7348 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7359 if (g_ascii_isspace (*p)) {
7366 return 0; /* missing assembly name */
7367 if (!assembly_name_to_aname (&info->assembly, p))
7373 if (info->assembly.name)
7376 // *w = 0; /* terminate class name */
7378 if (!info->name || !*info->name)
7382 /* add other consistency checks */
7387 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7389 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7393 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7395 gboolean type_resolve = FALSE;
7397 MonoImage *rootimage = image;
7399 if (info->assembly.name) {
7400 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7401 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7403 * This could happen in the AOT compiler case when the search hook is not
7406 assembly = image->assembly;
7408 /* then we must load the assembly ourselve - see #60439 */
7409 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7413 image = assembly->image;
7414 } else if (!image) {
7415 image = mono_defaults.corlib;
7418 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7419 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7420 image = mono_defaults.corlib;
7421 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7428 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7433 gboolean bounded = FALSE;
7436 image = mono_defaults.corlib;
7439 klass = mono_class_from_name_case (image, info->name_space, info->name);
7441 klass = mono_class_from_name (image, info->name_space, info->name);
7444 for (mod = info->nested; mod; mod = mod->next) {
7445 gpointer iter = NULL;
7449 mono_class_init (parent);
7451 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7453 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7456 if (strcmp (klass->name, mod->data) == 0)
7466 if (info->type_arguments) {
7467 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7468 MonoReflectionType *the_type;
7472 for (i = 0; i < info->type_arguments->len; i++) {
7473 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7475 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7476 if (!type_args [i]) {
7482 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7484 instance = mono_reflection_bind_generic_parameters (
7485 the_type, info->type_arguments->len, type_args);
7491 klass = mono_class_from_mono_type (instance);
7494 for (mod = info->modifiers; mod; mod = mod->next) {
7495 modval = GPOINTER_TO_UINT (mod->data);
7496 if (!modval) { /* byref: must be last modifier */
7497 return &klass->this_arg;
7498 } else if (modval == -1) {
7499 klass = mono_ptr_class_get (&klass->byval_arg);
7500 } else if (modval == -2) {
7502 } else { /* array rank */
7503 klass = mono_bounded_array_class_get (klass, modval, bounded);
7507 return &klass->byval_arg;
7511 * mono_reflection_get_type:
7512 * @image: a metadata context
7513 * @info: type description structure
7514 * @ignorecase: flag for case-insensitive string compares
7515 * @type_resolve: whenever type resolve was already tried
7517 * Build a MonoType from the type description in @info.
7522 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7523 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7527 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7529 MonoReflectionAssemblyBuilder *abuilder;
7533 g_assert (assembly->dynamic);
7534 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7536 /* Enumerate all modules */
7539 if (abuilder->modules) {
7540 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7541 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7542 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7548 if (!type && abuilder->loaded_modules) {
7549 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7550 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7551 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7561 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7564 MonoReflectionAssembly *assembly;
7568 if (image && image->dynamic)
7569 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7571 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7574 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7581 *type_resolve = TRUE;
7584 /* Reconstruct the type name */
7585 fullName = g_string_new ("");
7586 if (info->name_space && (info->name_space [0] != '\0'))
7587 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7589 g_string_printf (fullName, "%s", info->name);
7590 for (mod = info->nested; mod; mod = mod->next)
7591 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7593 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7595 if (assembly->assembly->dynamic)
7596 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7598 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7601 g_string_free (fullName, TRUE);
7606 mono_reflection_free_type_info (MonoTypeNameParse *info)
7608 g_list_free (info->modifiers);
7609 g_list_free (info->nested);
7611 if (info->type_arguments) {
7614 for (i = 0; i < info->type_arguments->len; i++) {
7615 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7617 mono_reflection_free_type_info (subinfo);
7618 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7622 g_ptr_array_free (info->type_arguments, TRUE);
7627 * mono_reflection_type_from_name:
7629 * @image: a metadata context (can be NULL).
7631 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7632 * it defaults to get the type from @image or, if @image is NULL or loading
7633 * from it fails, uses corlib.
7637 mono_reflection_type_from_name (char *name, MonoImage *image)
7639 MonoType *type = NULL;
7640 MonoTypeNameParse info;
7643 /* Make a copy since parse_type modifies its argument */
7644 tmp = g_strdup (name);
7646 /*g_print ("requested type %s\n", str);*/
7647 if (mono_reflection_parse_type (tmp, &info)) {
7648 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7652 mono_reflection_free_type_info (&info);
7657 * mono_reflection_get_token:
7659 * Return the metadata token of OBJ which should be an object
7660 * representing a metadata element.
7663 mono_reflection_get_token (MonoObject *obj)
7668 klass = obj->vtable->klass;
7670 if (strcmp (klass->name, "MethodBuilder") == 0) {
7671 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7673 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7674 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7675 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7677 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7678 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7679 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7681 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7682 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7683 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7684 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7685 } else if (strcmp (klass->name, "MonoType") == 0) {
7686 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7687 MonoClass *mc = mono_class_from_mono_type (type);
7688 if (!mono_class_init (mc))
7689 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7691 token = mc->type_token;
7692 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7693 strcmp (klass->name, "MonoMethod") == 0 ||
7694 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7695 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7696 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7697 if (m->method->is_inflated) {
7698 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7699 return inflated->declaring->token;
7701 token = m->method->token;
7703 } else if (strcmp (klass->name, "MonoField") == 0) {
7704 MonoReflectionField *f = (MonoReflectionField*)obj;
7706 if (is_field_on_inst (f->field)) {
7707 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7708 int field_index = f->field - dgclass->fields;
7711 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7712 obj = dgclass->field_objects [field_index];
7713 return mono_reflection_get_token (obj);
7715 token = mono_class_get_field_token (f->field);
7716 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7717 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7719 token = mono_class_get_property_token (p->property);
7720 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7721 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7723 token = mono_class_get_event_token (p->event);
7724 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7725 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7726 MonoClass *member_class = mono_object_class (p->MemberImpl);
7727 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7729 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7730 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7731 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7734 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7735 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7737 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7738 MonoException *ex = mono_get_exception_not_implemented (msg);
7740 mono_raise_exception (ex);
7747 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7749 int slen, type = t->type;
7750 MonoClass *tklass = t->data.klass;
7756 case MONO_TYPE_BOOLEAN: {
7757 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7762 case MONO_TYPE_CHAR:
7764 case MONO_TYPE_I2: {
7765 guint16 *val = g_malloc (sizeof (guint16));
7770 #if SIZEOF_VOID_P == 4
7776 case MONO_TYPE_I4: {
7777 guint32 *val = g_malloc (sizeof (guint32));
7782 #if SIZEOF_VOID_P == 8
7783 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7787 case MONO_TYPE_I8: {
7788 guint64 *val = g_malloc (sizeof (guint64));
7793 case MONO_TYPE_R8: {
7794 double *val = g_malloc (sizeof (double));
7799 case MONO_TYPE_VALUETYPE:
7800 if (t->data.klass->enumtype) {
7801 type = mono_class_enum_basetype (t->data.klass)->type;
7804 MonoClass *k = t->data.klass;
7806 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7807 guint64 *val = g_malloc (sizeof (guint64));
7813 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7816 case MONO_TYPE_STRING:
7817 if (*p == (char)0xFF) {
7821 slen = mono_metadata_decode_value (p, &p);
7823 return mono_string_new_len (mono_domain_get (), p, slen);
7824 case MONO_TYPE_CLASS: {
7827 if (*p == (char)0xFF) {
7832 slen = mono_metadata_decode_value (p, &p);
7833 n = g_memdup (p, slen + 1);
7835 t = mono_reflection_type_from_name (n, image);
7837 g_warning ("Cannot load type '%s'", n);
7841 return mono_type_get_object (mono_domain_get (), t);
7845 case MONO_TYPE_OBJECT: {
7848 MonoClass *subc = NULL;
7853 } else if (subt == 0x0E) {
7854 type = MONO_TYPE_STRING;
7856 } else if (subt == 0x1D) {
7857 MonoType simple_type = {{0}};
7862 /* See Partition II, Appendix B3 */
7863 etype = MONO_TYPE_OBJECT;
7864 type = MONO_TYPE_SZARRAY;
7865 simple_type.type = etype;
7866 tklass = mono_class_from_mono_type (&simple_type);
7868 } else if (subt == 0x55) {
7871 slen = mono_metadata_decode_value (p, &p);
7872 n = g_memdup (p, slen + 1);
7874 t = mono_reflection_type_from_name (n, image);
7876 g_error ("Cannot load type '%s'", n);
7879 subc = mono_class_from_mono_type (t);
7880 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7881 MonoType simple_type = {{0}};
7882 simple_type.type = subt;
7883 subc = mono_class_from_mono_type (&simple_type);
7885 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7887 val = load_cattr_value (image, &subc->byval_arg, p, end);
7888 obj = mono_object_new (mono_domain_get (), subc);
7889 g_assert (!subc->has_references);
7890 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7894 case MONO_TYPE_SZARRAY: {
7896 guint32 i, alen, basetype;
7899 if (alen == 0xffffffff) {
7903 arr = mono_array_new (mono_domain_get(), tklass, alen);
7904 basetype = tklass->byval_arg.type;
7905 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7906 basetype = mono_class_enum_basetype (tklass)->type;
7911 case MONO_TYPE_BOOLEAN:
7912 for (i = 0; i < alen; i++) {
7913 MonoBoolean val = *p++;
7914 mono_array_set (arr, MonoBoolean, i, val);
7917 case MONO_TYPE_CHAR:
7920 for (i = 0; i < alen; i++) {
7921 guint16 val = read16 (p);
7922 mono_array_set (arr, guint16, i, val);
7929 for (i = 0; i < alen; i++) {
7930 guint32 val = read32 (p);
7931 mono_array_set (arr, guint32, i, val);
7936 for (i = 0; i < alen; i++) {
7939 mono_array_set (arr, double, i, val);
7945 for (i = 0; i < alen; i++) {
7946 guint64 val = read64 (p);
7947 mono_array_set (arr, guint64, i, val);
7951 case MONO_TYPE_CLASS:
7952 case MONO_TYPE_OBJECT:
7953 case MONO_TYPE_STRING:
7954 for (i = 0; i < alen; i++) {
7955 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7956 mono_array_setref (arr, i, item);
7960 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7966 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7972 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7974 static MonoClass *klass;
7975 static MonoMethod *ctor;
7977 void *params [2], *unboxed;
7980 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7982 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7984 params [0] = mono_type_get_object (mono_domain_get (), t);
7986 retval = mono_object_new (mono_domain_get (), klass);
7987 unboxed = mono_object_unbox (retval);
7988 mono_runtime_invoke (ctor, unboxed, params, NULL);
7994 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7996 static MonoClass *klass;
7997 static MonoMethod *ctor;
7999 void *unboxed, *params [2];
8002 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8004 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8007 params [1] = typedarg;
8008 retval = mono_object_new (mono_domain_get (), klass);
8009 unboxed = mono_object_unbox (retval);
8010 mono_runtime_invoke (ctor, unboxed, params, NULL);
8016 type_is_reference (MonoType *type)
8018 switch (type->type) {
8019 case MONO_TYPE_BOOLEAN:
8020 case MONO_TYPE_CHAR:
8033 case MONO_TYPE_VALUETYPE:
8041 free_param_data (MonoMethodSignature *sig, void **params) {
8043 for (i = 0; i < sig->param_count; ++i) {
8044 if (!type_is_reference (sig->params [i]))
8045 g_free (params [i]);
8050 * Find the field index in the metadata FieldDef table.
8053 find_field_index (MonoClass *klass, MonoClassField *field) {
8056 for (i = 0; i < klass->field.count; ++i) {
8057 if (field == &klass->fields [i])
8058 return klass->field.first + 1 + i;
8064 * Find the property index in the metadata Property table.
8067 find_property_index (MonoClass *klass, MonoProperty *property) {
8070 for (i = 0; i < klass->ext->property.count; ++i) {
8071 if (property == &klass->ext->properties [i])
8072 return klass->ext->property.first + 1 + i;
8078 * Find the event index in the metadata Event table.
8081 find_event_index (MonoClass *klass, MonoEvent *event) {
8084 for (i = 0; i < klass->ext->event.count; ++i) {
8085 if (event == &klass->ext->events [i])
8086 return klass->ext->event.first + 1 + i;
8092 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8094 const char *p = (const char*)data;
8096 guint32 i, j, num_named;
8098 void *params_buf [32];
8100 MonoMethodSignature *sig;
8102 mono_error_init (error);
8104 mono_class_init (method->klass);
8106 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8107 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8112 attr = mono_object_new (mono_domain_get (), method->klass);
8113 mono_runtime_invoke (method, attr, NULL, NULL);
8117 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8120 /*g_print ("got attr %s\n", method->klass->name);*/
8122 sig = mono_method_signature (method);
8123 if (sig->param_count < 32)
8124 params = params_buf;
8126 /* Allocate using GC so it gets GC tracking */
8127 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8131 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8132 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8136 attr = mono_object_new (mono_domain_get (), method->klass);
8137 mono_runtime_invoke (method, attr, params, NULL);
8138 free_param_data (method->signature, params);
8139 num_named = read16 (named);
8141 for (j = 0; j < num_named; j++) {
8143 char *name, named_type, data_type;
8144 named_type = *named++;
8145 data_type = *named++; /* type of data */
8146 if (data_type == MONO_TYPE_SZARRAY)
8147 data_type = *named++;
8148 if (data_type == MONO_TYPE_ENUM) {
8151 type_len = mono_metadata_decode_blob_size (named, &named);
8152 type_name = g_malloc (type_len + 1);
8153 memcpy (type_name, named, type_len);
8154 type_name [type_len] = 0;
8156 /* FIXME: lookup the type and check type consistency */
8159 name_len = mono_metadata_decode_blob_size (named, &named);
8160 name = g_malloc (name_len + 1);
8161 memcpy (name, named, name_len);
8162 name [name_len] = 0;
8164 if (named_type == 0x53) {
8165 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8166 void *val = load_cattr_value (image, field->type, named, &named);
8167 mono_field_set_value (attr, field, val);
8168 if (!type_is_reference (field->type))
8170 } else if (named_type == 0x54) {
8173 MonoType *prop_type;
8175 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8176 /* can we have more that 1 arg in a custom attr named property? */
8177 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8178 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8179 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8180 mono_property_set_value (prop, attr, pparams, NULL);
8181 if (!type_is_reference (prop_type))
8182 g_free (pparams [0]);
8187 if (params != params_buf)
8188 mono_gc_free_fixed (params);
8194 * mono_reflection_create_custom_attr_data_args:
8196 * Create an array of typed and named arguments from the cattr blob given by DATA.
8197 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8198 * NAMED_ARG_INFO will contain information about the named arguments.
8201 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)
8203 MonoArray *typedargs, *namedargs;
8204 MonoClass *attrklass;
8206 const char *p = (const char*)data;
8208 guint32 i, j, num_named;
8209 CattrNamedArg *arginfo = NULL;
8211 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8214 mono_class_init (method->klass);
8218 *named_arg_info = NULL;
8220 domain = mono_domain_get ();
8222 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8225 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8229 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8233 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8234 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8235 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8236 mono_array_setref (typedargs, i, obj);
8238 if (!type_is_reference (mono_method_signature (method)->params [i]))
8243 num_named = read16 (named);
8244 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8246 attrklass = method->klass;
8248 arginfo = g_new0 (CattrNamedArg, num_named);
8249 *named_arg_info = arginfo;
8251 for (j = 0; j < num_named; j++) {
8253 char *name, named_type, data_type;
8254 named_type = *named++;
8255 data_type = *named++; /* type of data */
8256 if (data_type == MONO_TYPE_SZARRAY)
8257 data_type = *named++;
8258 if (data_type == MONO_TYPE_ENUM) {
8261 type_len = mono_metadata_decode_blob_size (named, &named);
8262 type_name = g_malloc (type_len + 1);
8263 memcpy (type_name, named, type_len);
8264 type_name [type_len] = 0;
8266 /* FIXME: lookup the type and check type consistency */
8269 name_len = mono_metadata_decode_blob_size (named, &named);
8270 name = g_malloc (name_len + 1);
8271 memcpy (name, named, name_len);
8272 name [name_len] = 0;
8274 if (named_type == 0x53) {
8276 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8279 arginfo [j].type = field->type;
8280 arginfo [j].field = field;
8282 val = load_cattr_value (image, field->type, named, &named);
8283 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8284 mono_array_setref (namedargs, j, obj);
8285 if (!type_is_reference (field->type))
8287 } else if (named_type == 0x54) {
8289 MonoType *prop_type;
8290 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8293 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8294 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8296 arginfo [j].type = prop_type;
8297 arginfo [j].prop = prop;
8299 val = load_cattr_value (image, prop_type, named, &named);
8300 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8301 mono_array_setref (namedargs, j, obj);
8302 if (!type_is_reference (prop_type))
8308 *typed_args = typedargs;
8309 *named_args = namedargs;
8313 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8316 MonoArray *typedargs, *namedargs;
8319 CattrNamedArg *arginfo;
8328 image = assembly->assembly->image;
8329 method = ref_method->method;
8330 domain = mono_object_domain (ref_method);
8332 if (!mono_class_init (method->klass))
8333 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8335 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8336 if (mono_loader_get_last_error ())
8337 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8339 if (!typedargs || !namedargs)
8342 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8343 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8344 MonoObject *typedarg;
8346 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8347 mono_array_setref (typedargs, i, typedarg);
8350 for (i = 0; i < mono_array_length (namedargs); ++i) {
8351 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8352 MonoObject *typedarg, *namedarg, *minfo;
8354 if (arginfo [i].prop)
8355 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8357 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8359 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8360 namedarg = create_cattr_named_arg (minfo, typedarg);
8362 mono_array_setref (namedargs, i, namedarg);
8365 *ctor_args = typedargs;
8366 *named_args = namedargs;
8370 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8372 static MonoMethod *ctor;
8377 g_assert (image->assembly);
8380 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8382 domain = mono_domain_get ();
8383 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8384 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8385 params [1] = mono_assembly_get_object (domain, image->assembly);
8386 params [2] = (gpointer)&cattr->data;
8387 params [3] = &cattr->data_size;
8388 mono_runtime_invoke (ctor, attr, params, NULL);
8393 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8399 mono_error_init (error);
8402 for (i = 0; i < cinfo->num_attrs; ++i) {
8403 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8407 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8409 for (i = 0; i < cinfo->num_attrs; ++i) {
8410 if (!cinfo->attrs [i].ctor)
8411 /* The cattr type is not finished yet */
8412 /* We should include the type name but cinfo doesn't contain it */
8413 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8414 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8415 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8416 if (!mono_error_ok (error))
8418 mono_array_setref (result, n, attr);
8426 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8430 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8434 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8440 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8441 for (i = 0; i < cinfo->num_attrs; ++i) {
8442 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8443 mono_array_setref (result, i, attr);
8449 * mono_custom_attrs_from_index:
8451 * Returns: NULL if no attributes are found or if a loading error occurs.
8454 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8456 guint32 mtoken, i, len;
8457 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8459 MonoCustomAttrInfo *ainfo;
8460 GList *tmp, *list = NULL;
8463 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8465 i = mono_metadata_custom_attrs_from_index (image, idx);
8469 while (i < ca->rows) {
8470 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8472 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8475 len = g_list_length (list);
8478 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8479 ainfo->num_attrs = len;
8480 ainfo->image = image;
8481 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8482 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8483 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8484 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8485 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8486 mtoken |= MONO_TOKEN_METHOD_DEF;
8488 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8489 mtoken |= MONO_TOKEN_MEMBER_REF;
8492 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8495 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8496 if (!ainfo->attrs [i].ctor) {
8497 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8503 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8504 /*FIXME raising an exception here doesn't make any sense*/
8505 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8510 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8511 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8512 ainfo->attrs [i].data = (guchar*)data;
8520 mono_custom_attrs_from_method (MonoMethod *method)
8525 * An instantiated method has the same cattrs as the generic method definition.
8527 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8528 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8530 if (method->is_inflated)
8531 method = ((MonoMethodInflated *) method)->declaring;
8533 if (method->dynamic || method->klass->image->dynamic)
8534 return lookup_custom_attr (method->klass->image, method);
8537 /* Synthetic methods */
8540 idx = mono_method_get_index (method);
8541 idx <<= MONO_CUSTOM_ATTR_BITS;
8542 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8543 return mono_custom_attrs_from_index (method->klass->image, idx);
8547 mono_custom_attrs_from_class (MonoClass *klass)
8551 if (klass->generic_class)
8552 klass = klass->generic_class->container_class;
8554 if (klass->image->dynamic)
8555 return lookup_custom_attr (klass->image, klass);
8557 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8558 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8559 idx <<= MONO_CUSTOM_ATTR_BITS;
8560 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8562 idx = mono_metadata_token_index (klass->type_token);
8563 idx <<= MONO_CUSTOM_ATTR_BITS;
8564 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8566 return mono_custom_attrs_from_index (klass->image, idx);
8570 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8574 if (assembly->image->dynamic)
8575 return lookup_custom_attr (assembly->image, assembly);
8576 idx = 1; /* there is only one assembly */
8577 idx <<= MONO_CUSTOM_ATTR_BITS;
8578 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8579 return mono_custom_attrs_from_index (assembly->image, idx);
8582 static MonoCustomAttrInfo*
8583 mono_custom_attrs_from_module (MonoImage *image)
8588 return lookup_custom_attr (image, image);
8589 idx = 1; /* there is only one module */
8590 idx <<= MONO_CUSTOM_ATTR_BITS;
8591 idx |= MONO_CUSTOM_ATTR_MODULE;
8592 return mono_custom_attrs_from_index (image, idx);
8596 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8600 if (klass->image->dynamic) {
8601 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8602 return lookup_custom_attr (klass->image, property);
8604 idx = find_property_index (klass, property);
8605 idx <<= MONO_CUSTOM_ATTR_BITS;
8606 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8607 return mono_custom_attrs_from_index (klass->image, idx);
8611 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8615 if (klass->image->dynamic) {
8616 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8617 return lookup_custom_attr (klass->image, event);
8619 idx = find_event_index (klass, event);
8620 idx <<= MONO_CUSTOM_ATTR_BITS;
8621 idx |= MONO_CUSTOM_ATTR_EVENT;
8622 return mono_custom_attrs_from_index (klass->image, idx);
8626 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8629 if (klass->image->dynamic) {
8630 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8631 return lookup_custom_attr (klass->image, field);
8633 idx = find_field_index (klass, field);
8634 idx <<= MONO_CUSTOM_ATTR_BITS;
8635 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8636 return mono_custom_attrs_from_index (klass->image, idx);
8640 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8643 guint32 i, idx, method_index;
8644 guint32 param_list, param_last, param_pos, found;
8646 MonoReflectionMethodAux *aux;
8649 * An instantiated method has the same cattrs as the generic method definition.
8651 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8652 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8654 if (method->is_inflated)
8655 method = ((MonoMethodInflated *) method)->declaring;
8657 if (method->klass->image->dynamic) {
8658 MonoCustomAttrInfo *res, *ainfo;
8661 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8662 if (!aux || !aux->param_cattr)
8665 /* Need to copy since it will be freed later */
8666 ainfo = aux->param_cattr [param];
8669 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8670 res = g_malloc0 (size);
8671 memcpy (res, ainfo, size);
8675 image = method->klass->image;
8676 method_index = mono_method_get_index (method);
8679 ca = &image->tables [MONO_TABLE_METHOD];
8681 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8682 if (method_index == ca->rows) {
8683 ca = &image->tables [MONO_TABLE_PARAM];
8684 param_last = ca->rows + 1;
8686 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8687 ca = &image->tables [MONO_TABLE_PARAM];
8690 for (i = param_list; i < param_last; ++i) {
8691 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8692 if (param_pos == param) {
8700 idx <<= MONO_CUSTOM_ATTR_BITS;
8701 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8702 return mono_custom_attrs_from_index (image, idx);
8706 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8710 for (i = 0; i < ainfo->num_attrs; ++i) {
8711 klass = ainfo->attrs [i].ctor->klass;
8712 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8719 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8726 for (i = 0; i < ainfo->num_attrs; ++i) {
8727 klass = ainfo->attrs [i].ctor->klass;
8728 if (mono_class_has_parent (klass, attr_klass)) {
8733 if (attr_index == -1)
8736 attrs = mono_custom_attrs_construct (ainfo);
8738 return mono_array_get (attrs, MonoObject*, attr_index);
8744 * mono_reflection_get_custom_attrs_info:
8745 * @obj: a reflection object handle
8747 * Return the custom attribute info for attributes defined for the
8748 * reflection handle @obj. The objects.
8750 * FIXME this function leaks like a sieve for SRE objects.
8753 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8756 MonoCustomAttrInfo *cinfo = NULL;
8758 klass = obj->vtable->klass;
8759 if (klass == mono_defaults.monotype_class) {
8760 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8761 klass = mono_class_from_mono_type (type);
8762 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8763 cinfo = mono_custom_attrs_from_class (klass);
8764 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8765 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8766 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8767 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8768 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8769 cinfo = mono_custom_attrs_from_module (module->image);
8770 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8771 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8772 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8773 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8774 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8775 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8776 } else if (strcmp ("MonoField", klass->name) == 0) {
8777 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8778 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8779 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8780 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8781 cinfo = mono_custom_attrs_from_method (rmethod->method);
8782 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8783 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8784 cinfo = mono_custom_attrs_from_method (rmethod->method);
8785 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8786 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8787 MonoClass *member_class = mono_object_class (param->MemberImpl);
8788 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8789 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8790 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8791 } else if (is_sr_mono_property (member_class)) {
8792 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8794 if (!(method = prop->property->get))
8795 method = prop->property->set;
8798 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8800 #ifndef DISABLE_REFLECTION_EMIT
8801 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8802 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8803 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8804 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8805 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8806 MonoMethod *method = NULL;
8807 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8808 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8809 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8810 method = ((MonoReflectionMethod *)c->cb)->method;
8812 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8814 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8818 char *type_name = mono_type_get_full_name (member_class);
8819 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8820 MonoException *ex = mono_get_exception_not_supported (msg);
8823 mono_raise_exception (ex);
8825 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8826 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8827 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8828 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8829 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8830 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8831 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8832 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8833 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8834 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8835 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8836 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8837 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8838 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8839 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8840 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8841 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8842 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8843 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8844 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8845 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8846 } else { /* handle other types here... */
8847 g_error ("get custom attrs not yet supported for %s", klass->name);
8854 * mono_reflection_get_custom_attrs_by_type:
8855 * @obj: a reflection object handle
8857 * Return an array with all the custom attributes defined of the
8858 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8859 * of that type are returned. The objects are fully build. Return NULL if a loading error
8863 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8866 MonoCustomAttrInfo *cinfo;
8868 mono_error_init (error);
8870 cinfo = mono_reflection_get_custom_attrs_info (obj);
8872 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8874 mono_custom_attrs_free (cinfo);
8876 if (mono_loader_get_last_error ())
8878 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8885 * mono_reflection_get_custom_attrs:
8886 * @obj: a reflection object handle
8888 * Return an array with all the custom attributes defined of the
8889 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8893 mono_reflection_get_custom_attrs (MonoObject *obj)
8897 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8901 * mono_reflection_get_custom_attrs_data:
8902 * @obj: a reflection obj handle
8904 * Returns an array of System.Reflection.CustomAttributeData,
8905 * which include information about attributes reflected on
8906 * types loaded using the Reflection Only methods
8909 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8912 MonoCustomAttrInfo *cinfo;
8914 cinfo = mono_reflection_get_custom_attrs_info (obj);
8916 result = mono_custom_attrs_data_construct (cinfo);
8918 mono_custom_attrs_free (cinfo);
8920 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8925 static MonoReflectionType*
8926 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8928 static MonoMethod *method_get_underlying_system_type = NULL;
8929 MonoMethod *usertype_method;
8931 if (!method_get_underlying_system_type)
8932 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8933 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8934 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8939 is_corlib_type (MonoClass *class)
8941 return class->image == mono_defaults.corlib;
8944 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8945 static MonoClass *cached_class; \
8947 return cached_class == _class; \
8948 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8949 cached_class = _class; \
8956 #ifndef DISABLE_REFLECTION_EMIT
8958 is_sre_array (MonoClass *class)
8960 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8964 is_sre_byref (MonoClass *class)
8966 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8970 is_sre_pointer (MonoClass *class)
8972 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8976 is_sre_generic_instance (MonoClass *class)
8978 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8982 is_sre_type_builder (MonoClass *class)
8984 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8988 is_sre_method_builder (MonoClass *class)
8990 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8994 is_sre_ctor_builder (MonoClass *class)
8996 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9000 is_sre_field_builder (MonoClass *class)
9002 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9006 is_sre_method_on_tb_inst (MonoClass *class)
9008 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9012 is_sre_ctor_on_tb_inst (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9018 mono_reflection_type_get_handle (MonoReflectionType* ref)
9026 if (is_usertype (ref)) {
9027 ref = mono_reflection_type_get_underlying_system_type (ref);
9028 if (ref == NULL || is_usertype (ref))
9034 class = mono_object_class (ref);
9036 if (is_sre_array (class)) {
9038 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9039 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9041 if (sre_array->rank == 0) //single dimentional array
9042 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9044 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9045 sre_array->type.type = res;
9047 } else if (is_sre_byref (class)) {
9049 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9050 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9052 res = &mono_class_from_mono_type (base)->this_arg;
9053 sre_byref->type.type = res;
9055 } else if (is_sre_pointer (class)) {
9057 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9058 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9060 res = &mono_ptr_class_get (base)->byval_arg;
9061 sre_pointer->type.type = res;
9063 } else if (is_sre_generic_instance (class)) {
9064 MonoType *res, **types;
9065 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9068 count = mono_array_length (gclass->type_arguments);
9069 types = g_new0 (MonoType*, count);
9070 for (i = 0; i < count; ++i) {
9071 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9072 types [i] = mono_reflection_type_get_handle (t);
9079 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9082 gclass->type.type = res;
9086 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9093 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9095 mono_reflection_type_get_handle (type);
9099 mono_reflection_register_with_runtime (MonoReflectionType *type)
9101 MonoType *res = mono_reflection_type_get_handle (type);
9102 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9106 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9108 class = mono_class_from_mono_type (res);
9110 mono_loader_lock (); /*same locking as mono_type_get_object*/
9111 mono_domain_lock (domain);
9113 if (!class->image->dynamic) {
9114 mono_class_setup_supertypes (class);
9116 if (!domain->type_hash)
9117 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9118 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9119 mono_g_hash_table_insert (domain->type_hash, res, type);
9121 mono_domain_unlock (domain);
9122 mono_loader_unlock ();
9126 * LOCKING: Assumes the loader lock is held.
9128 static MonoMethodSignature*
9129 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9130 MonoMethodSignature *sig;
9133 count = parameters? mono_array_length (parameters): 0;
9135 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9136 sig->param_count = count;
9137 sig->sentinelpos = -1; /* FIXME */
9138 for (i = 0; i < count; ++i)
9139 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9144 * LOCKING: Assumes the loader lock is held.
9146 static MonoMethodSignature*
9147 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9148 MonoMethodSignature *sig;
9150 sig = parameters_to_signature (image, ctor->parameters);
9151 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9152 sig->ret = &mono_defaults.void_class->byval_arg;
9157 * LOCKING: Assumes the loader lock is held.
9159 static MonoMethodSignature*
9160 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9161 MonoMethodSignature *sig;
9163 sig = parameters_to_signature (image, method->parameters);
9164 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9165 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9166 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9170 static MonoMethodSignature*
9171 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9172 MonoMethodSignature *sig;
9174 sig = parameters_to_signature (NULL, method->parameters);
9175 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9177 sig->generic_param_count = 0;
9182 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9184 MonoClass *klass = mono_object_class (prop);
9185 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9186 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9187 *name = mono_string_to_utf8 (pb->name);
9188 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9190 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9191 *name = g_strdup (p->property->name);
9192 if (p->property->get)
9193 *type = mono_method_signature (p->property->get)->ret;
9195 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9200 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9202 MonoClass *klass = mono_object_class (field);
9203 if (strcmp (klass->name, "FieldBuilder") == 0) {
9204 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9205 *name = mono_string_to_utf8 (fb->name);
9206 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9208 MonoReflectionField *f = (MonoReflectionField *)field;
9209 *name = g_strdup (mono_field_get_name (f->field));
9210 *type = f->field->type;
9214 #else /* DISABLE_REFLECTION_EMIT */
9217 mono_reflection_register_with_runtime (MonoReflectionType *type)
9223 is_sre_type_builder (MonoClass *class)
9229 is_sre_generic_instance (MonoClass *class)
9235 init_type_builder_generics (MonoObject *type)
9239 #endif /* !DISABLE_REFLECTION_EMIT */
9243 is_sr_mono_field (MonoClass *class)
9245 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9249 is_sr_mono_property (MonoClass *class)
9251 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9255 is_sr_mono_method (MonoClass *class)
9257 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9261 is_sr_mono_cmethod (MonoClass *class)
9263 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9267 is_sr_mono_generic_method (MonoClass *class)
9269 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9273 is_sr_mono_generic_cmethod (MonoClass *class)
9275 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9279 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9281 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9285 is_usertype (MonoReflectionType *ref)
9287 MonoClass *class = mono_object_class (ref);
9288 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9291 static MonoReflectionType*
9292 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9294 if (!type || type->type)
9297 if (is_usertype (type)) {
9298 type = mono_reflection_type_get_underlying_system_type (type);
9299 if (is_usertype (type))
9300 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9306 * Encode a value in a custom attribute stream of bytes.
9307 * The value to encode is either supplied as an object in argument val
9308 * (valuetypes are boxed), or as a pointer to the data in the
9310 * @type represents the type of the value
9311 * @buffer is the start of the buffer
9312 * @p the current position in the buffer
9313 * @buflen contains the size of the buffer and is used to return the new buffer size
9314 * if this needs to be realloced.
9315 * @retbuffer and @retp return the start and the position of the buffer
9318 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9320 MonoTypeEnum simple_type;
9322 if ((p-buffer) + 10 >= *buflen) {
9325 newbuf = g_realloc (buffer, *buflen);
9326 p = newbuf + (p-buffer);
9330 argval = ((char*)arg + sizeof (MonoObject));
9331 simple_type = type->type;
9333 switch (simple_type) {
9334 case MONO_TYPE_BOOLEAN:
9339 case MONO_TYPE_CHAR:
9342 swap_with_size (p, argval, 2, 1);
9348 swap_with_size (p, argval, 4, 1);
9352 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9362 swap_with_size (p, argval, 8, 1);
9368 swap_with_size (p, argval, 8, 1);
9371 case MONO_TYPE_VALUETYPE:
9372 if (type->data.klass->enumtype) {
9373 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9376 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9379 case MONO_TYPE_STRING: {
9386 str = mono_string_to_utf8 ((MonoString*)arg);
9387 slen = strlen (str);
9388 if ((p-buffer) + 10 + slen >= *buflen) {
9392 newbuf = g_realloc (buffer, *buflen);
9393 p = newbuf + (p-buffer);
9396 mono_metadata_encode_value (slen, p, &p);
9397 memcpy (p, str, slen);
9402 case MONO_TYPE_CLASS: {
9410 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9411 slen = strlen (str);
9412 if ((p-buffer) + 10 + slen >= *buflen) {
9416 newbuf = g_realloc (buffer, *buflen);
9417 p = newbuf + (p-buffer);
9420 mono_metadata_encode_value (slen, p, &p);
9421 memcpy (p, str, slen);
9426 case MONO_TYPE_SZARRAY: {
9428 MonoClass *eclass, *arg_eclass;
9431 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9434 len = mono_array_length ((MonoArray*)arg);
9436 *p++ = (len >> 8) & 0xff;
9437 *p++ = (len >> 16) & 0xff;
9438 *p++ = (len >> 24) & 0xff;
9440 *retbuffer = buffer;
9441 eclass = type->data.klass;
9442 arg_eclass = mono_object_class (arg)->element_class;
9445 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9446 eclass = mono_defaults.object_class;
9448 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9449 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9450 int elsize = mono_class_array_element_size (arg_eclass);
9451 for (i = 0; i < len; ++i) {
9452 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9455 } else if (eclass->valuetype && arg_eclass->valuetype) {
9456 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9457 int elsize = mono_class_array_element_size (eclass);
9458 for (i = 0; i < len; ++i) {
9459 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9463 for (i = 0; i < len; ++i) {
9464 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9469 case MONO_TYPE_OBJECT: {
9475 * The parameter type is 'object' but the type of the actual
9476 * argument is not. So we have to add type information to the blob
9477 * too. This is completely undocumented in the spec.
9481 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9486 klass = mono_object_class (arg);
9488 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9491 } else if (klass->enumtype) {
9493 } else if (klass == mono_defaults.string_class) {
9494 simple_type = MONO_TYPE_STRING;
9497 } else if (klass->rank == 1) {
9499 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9500 /* See Partition II, Appendix B3 */
9503 *p++ = klass->element_class->byval_arg.type;
9504 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9506 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9507 *p++ = simple_type = klass->byval_arg.type;
9510 g_error ("unhandled type in custom attr");
9512 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9513 slen = strlen (str);
9514 if ((p-buffer) + 10 + slen >= *buflen) {
9518 newbuf = g_realloc (buffer, *buflen);
9519 p = newbuf + (p-buffer);
9522 mono_metadata_encode_value (slen, p, &p);
9523 memcpy (p, str, slen);
9526 simple_type = mono_class_enum_basetype (klass)->type;
9530 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9533 *retbuffer = buffer;
9537 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9539 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9540 char *str = type_get_qualified_name (type, NULL);
9541 int slen = strlen (str);
9545 * This seems to be optional...
9548 mono_metadata_encode_value (slen, p, &p);
9549 memcpy (p, str, slen);
9552 } else if (type->type == MONO_TYPE_OBJECT) {
9554 } else if (type->type == MONO_TYPE_CLASS) {
9555 /* it should be a type: encode_cattr_value () has the check */
9558 mono_metadata_encode_value (type->type, p, &p);
9559 if (type->type == MONO_TYPE_SZARRAY)
9560 /* See the examples in Partition VI, Annex B */
9561 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9567 #ifndef DISABLE_REFLECTION_EMIT
9569 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9572 /* Preallocate a large enough buffer */
9573 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9574 char *str = type_get_qualified_name (type, NULL);
9577 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9578 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9584 len += strlen (name);
9586 if ((p-buffer) + 20 + len >= *buflen) {
9590 newbuf = g_realloc (buffer, *buflen);
9591 p = newbuf + (p-buffer);
9595 encode_field_or_prop_type (type, p, &p);
9597 len = strlen (name);
9598 mono_metadata_encode_value (len, p, &p);
9599 memcpy (p, name, len);
9601 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9603 *retbuffer = buffer;
9607 * mono_reflection_get_custom_attrs_blob:
9608 * @ctor: custom attribute constructor
9609 * @ctorArgs: arguments o the constructor
9615 * Creates the blob of data that needs to be saved in the metadata and that represents
9616 * the custom attributed described by @ctor, @ctorArgs etc.
9617 * Returns: a Byte array representing the blob of data.
9620 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9623 MonoMethodSignature *sig;
9628 MONO_ARCH_SAVE_REGS;
9630 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9631 /* sig is freed later so allocate it in the heap */
9632 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9634 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9637 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9639 p = buffer = g_malloc (buflen);
9640 /* write the prolog */
9643 for (i = 0; i < sig->param_count; ++i) {
9644 arg = mono_array_get (ctorArgs, MonoObject*, i);
9645 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9649 i += mono_array_length (properties);
9651 i += mono_array_length (fields);
9653 *p++ = (i >> 8) & 0xff;
9656 for (i = 0; i < mono_array_length (properties); ++i) {
9660 prop = mono_array_get (properties, gpointer, i);
9661 get_prop_name_and_type (prop, &pname, &ptype);
9662 *p++ = 0x54; /* PROPERTY signature */
9663 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9670 for (i = 0; i < mono_array_length (fields); ++i) {
9674 field = mono_array_get (fields, gpointer, i);
9675 get_field_name_and_type (field, &fname, &ftype);
9676 *p++ = 0x53; /* FIELD signature */
9677 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9682 g_assert (p - buffer <= buflen);
9683 buflen = p - buffer;
9684 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9685 p = mono_array_addr (result, char, 0);
9686 memcpy (p, buffer, buflen);
9688 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9694 * mono_reflection_setup_internal_class:
9695 * @tb: a TypeBuilder object
9697 * Creates a MonoClass that represents the TypeBuilder.
9698 * This is a trick that lets us simplify a lot of reflection code
9699 * (and will allow us to support Build and Run assemblies easier).
9702 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9705 MonoClass *klass, *parent;
9707 MONO_ARCH_SAVE_REGS;
9709 RESOLVE_TYPE (tb->parent);
9711 mono_loader_lock ();
9714 /* check so we can compile corlib correctly */
9715 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9716 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9717 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9719 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9725 /* the type has already being created: it means we just have to change the parent */
9726 if (tb->type.type) {
9727 klass = mono_class_from_mono_type (tb->type.type);
9728 klass->parent = NULL;
9729 /* fool mono_class_setup_parent */
9730 klass->supertypes = NULL;
9731 mono_class_setup_parent (klass, parent);
9732 mono_class_setup_mono_type (klass);
9733 mono_loader_unlock ();
9737 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9739 klass->image = &tb->module->dynamic_image->image;
9741 klass->inited = 1; /* we lie to the runtime */
9742 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9743 if (!mono_error_ok (&error))
9745 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9746 if (!mono_error_ok (&error))
9748 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9749 klass->flags = tb->attrs;
9751 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9753 klass->element_class = klass;
9755 if (mono_class_get_ref_info (klass) == NULL) {
9757 mono_class_set_ref_info (klass, tb);
9759 /* Put into cache so mono_class_get () will find it.
9760 Skip nested types as those should not be available on the global scope. */
9761 if (!tb->nesting_type) {
9762 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9764 klass->image->reflection_info_unregister_classes =
9765 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9768 g_assert (mono_class_get_ref_info (klass) == tb);
9771 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9772 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9774 if (parent != NULL) {
9775 mono_class_setup_parent (klass, parent);
9776 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9777 const char *old_n = klass->name;
9778 /* trick to get relative numbering right when compiling corlib */
9779 klass->name = "BuildingObject";
9780 mono_class_setup_parent (klass, mono_defaults.object_class);
9781 klass->name = old_n;
9784 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9785 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9786 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9787 klass->instance_size = sizeof (MonoObject);
9788 klass->size_inited = 1;
9789 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9792 mono_class_setup_mono_type (klass);
9794 mono_class_setup_supertypes (klass);
9797 * FIXME: handle interfaces.
9800 tb->type.type = &klass->byval_arg;
9802 if (tb->nesting_type) {
9803 g_assert (tb->nesting_type->type);
9804 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9807 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9809 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9811 mono_loader_unlock ();
9815 mono_loader_unlock ();
9816 mono_error_raise_exception (&error);
9820 * mono_reflection_setup_generic_class:
9821 * @tb: a TypeBuilder object
9823 * Setup the generic class before adding the first generic parameter.
9826 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9831 * mono_reflection_create_generic_class:
9832 * @tb: a TypeBuilder object
9834 * Creates the generic class after all generic parameters have been added.
9837 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9842 MONO_ARCH_SAVE_REGS;
9844 klass = mono_class_from_mono_type (tb->type.type);
9846 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9848 if (klass->generic_container || (count == 0))
9851 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9853 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9855 klass->generic_container->owner.klass = klass;
9856 klass->generic_container->type_argc = count;
9857 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9859 klass->is_generic = 1;
9861 for (i = 0; i < count; i++) {
9862 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9863 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9864 klass->generic_container->type_params [i] = *param;
9865 /*Make sure we are a diferent type instance */
9866 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9867 klass->generic_container->type_params [i].info.pklass = NULL;
9868 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9870 g_assert (klass->generic_container->type_params [i].param.owner);
9873 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9877 * mono_reflection_create_internal_class:
9878 * @tb: a TypeBuilder object
9880 * Actually create the MonoClass that is associated with the TypeBuilder.
9883 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9887 MONO_ARCH_SAVE_REGS;
9889 klass = mono_class_from_mono_type (tb->type.type);
9891 mono_loader_lock ();
9892 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9893 MonoReflectionFieldBuilder *fb;
9895 MonoType *enum_basetype;
9897 g_assert (tb->fields != NULL);
9898 g_assert (mono_array_length (tb->fields) >= 1);
9900 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9902 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9903 mono_loader_unlock ();
9907 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9908 klass->element_class = mono_class_from_mono_type (enum_basetype);
9909 if (!klass->element_class)
9910 klass->element_class = mono_class_from_mono_type (enum_basetype);
9913 * get the element_class from the current corlib.
9915 ec = default_class_from_mono_type (enum_basetype);
9916 klass->instance_size = ec->instance_size;
9917 klass->size_inited = 1;
9919 * this is almost safe to do with enums and it's needed to be able
9920 * to create objects of the enum type (for use in SetConstant).
9922 /* FIXME: Does this mean enums can't have method overrides ? */
9923 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9925 mono_loader_unlock ();
9928 static MonoMarshalSpec*
9929 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9930 MonoReflectionMarshal *minfo)
9932 MonoMarshalSpec *res;
9934 res = image_g_new0 (image, MonoMarshalSpec, 1);
9935 res->native = minfo->type;
9937 switch (minfo->type) {
9938 case MONO_NATIVE_LPARRAY:
9939 res->data.array_data.elem_type = minfo->eltype;
9940 if (minfo->has_size) {
9941 res->data.array_data.param_num = minfo->param_num;
9942 res->data.array_data.num_elem = minfo->count;
9943 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9946 res->data.array_data.param_num = -1;
9947 res->data.array_data.num_elem = -1;
9948 res->data.array_data.elem_mult = -1;
9952 case MONO_NATIVE_BYVALTSTR:
9953 case MONO_NATIVE_BYVALARRAY:
9954 res->data.array_data.num_elem = minfo->count;
9957 case MONO_NATIVE_CUSTOM:
9958 if (minfo->marshaltyperef)
9959 res->data.custom_data.custom_name =
9960 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9962 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9971 #endif /* !DISABLE_REFLECTION_EMIT */
9973 MonoReflectionMarshal*
9974 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9975 MonoMarshalSpec *spec)
9977 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9978 MonoReflectionMarshal *minfo;
9981 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9982 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9983 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9984 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9987 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9988 minfo->type = spec->native;
9990 switch (minfo->type) {
9991 case MONO_NATIVE_LPARRAY:
9992 minfo->eltype = spec->data.array_data.elem_type;
9993 minfo->count = spec->data.array_data.num_elem;
9994 minfo->param_num = spec->data.array_data.param_num;
9997 case MONO_NATIVE_BYVALTSTR:
9998 case MONO_NATIVE_BYVALARRAY:
9999 minfo->count = spec->data.array_data.num_elem;
10002 case MONO_NATIVE_CUSTOM:
10003 if (spec->data.custom_data.custom_name) {
10004 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10006 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10008 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10010 if (spec->data.custom_data.cookie)
10011 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10021 #ifndef DISABLE_REFLECTION_EMIT
10023 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10024 ReflectionMethodBuilder *rmb,
10025 MonoMethodSignature *sig)
10029 MonoMethodWrapper *wrapperm;
10030 MonoMarshalSpec **specs;
10031 MonoReflectionMethodAux *method_aux;
10036 mono_error_init (&error);
10038 * Methods created using a MethodBuilder should have their memory allocated
10039 * inside the image mempool, while dynamic methods should have their memory
10042 dynamic = rmb->refs != NULL;
10043 image = dynamic ? NULL : klass->image;
10046 g_assert (!klass->generic_class);
10048 mono_loader_lock ();
10050 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10051 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10052 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10054 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10056 wrapperm = (MonoMethodWrapper*)m;
10058 m->dynamic = dynamic;
10060 m->flags = rmb->attrs;
10061 m->iflags = rmb->iattrs;
10062 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10063 g_assert (mono_error_ok (&error));
10065 m->signature = sig;
10066 m->sre_method = TRUE;
10067 m->skip_visibility = rmb->skip_visibility;
10068 if (rmb->table_idx)
10069 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10071 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10072 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10073 m->string_ctor = 1;
10075 m->signature->pinvoke = 1;
10076 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10077 m->signature->pinvoke = 1;
10079 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10081 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10082 g_assert (mono_error_ok (&error));
10083 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10084 g_assert (mono_error_ok (&error));
10086 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10088 if (klass->image->dynamic)
10089 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10091 mono_loader_unlock ();
10094 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10095 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10096 MonoMethodHeader *header;
10098 gint32 max_stack, i;
10099 gint32 num_locals = 0;
10100 gint32 num_clauses = 0;
10104 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10105 code_size = rmb->ilgen->code_len;
10106 max_stack = rmb->ilgen->max_stack;
10107 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10108 if (rmb->ilgen->ex_handlers)
10109 num_clauses = method_count_clauses (rmb->ilgen);
10112 code = mono_array_addr (rmb->code, guint8, 0);
10113 code_size = mono_array_length (rmb->code);
10114 /* we probably need to run a verifier on the code... */
10124 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10125 header->code_size = code_size;
10126 header->code = image_g_malloc (image, code_size);
10127 memcpy ((char*)header->code, code, code_size);
10128 header->max_stack = max_stack;
10129 header->init_locals = rmb->init_locals;
10130 header->num_locals = num_locals;
10132 for (i = 0; i < num_locals; ++i) {
10133 MonoReflectionLocalBuilder *lb =
10134 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10136 header->locals [i] = image_g_new0 (image, MonoType, 1);
10137 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10140 header->num_clauses = num_clauses;
10142 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10143 rmb->ilgen, num_clauses);
10146 wrapperm->header = header;
10149 if (rmb->generic_params) {
10150 int count = mono_array_length (rmb->generic_params);
10151 MonoGenericContainer *container = rmb->generic_container;
10153 g_assert (container);
10155 container->type_argc = count;
10156 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10157 container->owner.method = m;
10159 m->is_generic = TRUE;
10160 mono_method_set_generic_container (m, container);
10162 for (i = 0; i < count; i++) {
10163 MonoReflectionGenericParam *gp =
10164 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10165 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10166 container->type_params [i] = *param;
10170 * The method signature might have pointers to generic parameters that belong to other methods.
10171 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10172 * generic parameters.
10174 for (i = 0; i < m->signature->param_count; ++i) {
10175 MonoType *t = m->signature->params [i];
10176 if (t->type == MONO_TYPE_MVAR) {
10177 MonoGenericParam *gparam = t->data.generic_param;
10178 if (gparam->num < count) {
10179 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10180 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10186 if (klass->generic_container) {
10187 container->parent = klass->generic_container;
10188 container->context.class_inst = klass->generic_container->context.class_inst;
10190 container->context.method_inst = mono_get_shared_generic_inst (container);
10194 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10198 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10200 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10201 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10202 for (i = 0; i < rmb->nrefs; ++i)
10203 data [i + 1] = rmb->refs [i];
10208 /* Parameter info */
10211 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10212 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10213 for (i = 0; i <= m->signature->param_count; ++i) {
10214 MonoReflectionParamBuilder *pb;
10215 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10216 if ((i > 0) && (pb->attrs)) {
10217 /* Make a copy since it might point to a shared type structure */
10218 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10219 m->signature->params [i - 1]->attrs = pb->attrs;
10222 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10223 MonoDynamicImage *assembly;
10224 guint32 idx, def_type, len;
10228 if (!method_aux->param_defaults) {
10229 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10230 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10232 assembly = (MonoDynamicImage*)klass->image;
10233 idx = encode_constant (assembly, pb->def_value, &def_type);
10234 /* Copy the data from the blob since it might get realloc-ed */
10235 p = assembly->blob.data + idx;
10236 len = mono_metadata_decode_blob_size (p, &p2);
10238 method_aux->param_defaults [i] = image_g_malloc (image, len);
10239 method_aux->param_default_types [i] = def_type;
10240 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10244 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10245 g_assert (mono_error_ok (&error));
10248 if (!method_aux->param_cattr)
10249 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10250 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10256 /* Parameter marshalling */
10259 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10260 MonoReflectionParamBuilder *pb;
10261 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10262 if (pb->marshal_info) {
10264 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10265 specs [pb->position] =
10266 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10270 if (specs != NULL) {
10272 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10273 method_aux->param_marshall = specs;
10276 if (klass->image->dynamic && method_aux)
10277 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10279 mono_loader_unlock ();
10285 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10287 ReflectionMethodBuilder rmb;
10288 MonoMethodSignature *sig;
10290 mono_loader_lock ();
10291 sig = ctor_builder_to_signature (klass->image, mb);
10292 mono_loader_unlock ();
10294 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10296 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10297 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10299 /* If we are in a generic class, we might be called multiple times from inflate_method */
10300 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10301 /* ilgen is no longer needed */
10305 return mb->mhandle;
10309 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10311 ReflectionMethodBuilder rmb;
10312 MonoMethodSignature *sig;
10314 mono_loader_lock ();
10315 sig = method_builder_to_signature (klass->image, mb);
10316 mono_loader_unlock ();
10318 reflection_methodbuilder_from_method_builder (&rmb, mb);
10320 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10321 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10323 /* If we are in a generic class, we might be called multiple times from inflate_method */
10324 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10325 /* ilgen is no longer needed */
10328 return mb->mhandle;
10331 static MonoClassField*
10332 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10334 MonoClassField *field;
10338 field = g_new0 (MonoClassField, 1);
10340 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10341 g_assert (mono_error_ok (&error));
10342 if (fb->attrs || fb->modreq || fb->modopt) {
10343 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10344 field->type->attrs = fb->attrs;
10346 g_assert (klass->image->dynamic);
10347 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10348 g_free (field->type);
10349 field->type = mono_metadata_type_dup (klass->image, custom);
10352 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10354 if (fb->offset != -1)
10355 field->offset = fb->offset;
10356 field->parent = klass;
10357 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10359 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10366 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10369 MonoReflectionTypeBuilder *tb = NULL;
10370 gboolean is_dynamic = FALSE;
10371 MonoDomain *domain;
10372 MonoClass *geninst;
10374 mono_loader_lock ();
10376 domain = mono_object_domain (type);
10378 if (is_sre_type_builder (mono_object_class (type))) {
10379 tb = (MonoReflectionTypeBuilder *) type;
10382 } else if (is_sre_generic_instance (mono_object_class (type))) {
10383 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10384 MonoReflectionType *gtd = rgi->generic_type;
10386 if (is_sre_type_builder (mono_object_class (gtd))) {
10387 tb = (MonoReflectionTypeBuilder *)gtd;
10392 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10393 if (tb && tb->generic_container)
10394 mono_reflection_create_generic_class (tb);
10396 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10397 if (!klass->generic_container) {
10398 mono_loader_unlock ();
10402 if (klass->wastypebuilder) {
10403 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10408 mono_loader_unlock ();
10410 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10412 return &geninst->byval_arg;
10416 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10418 MonoGenericClass *gclass;
10419 MonoGenericInst *inst;
10421 g_assert (klass->generic_container);
10423 inst = mono_metadata_get_generic_inst (type_argc, types);
10424 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10426 return mono_generic_class_get_class (gclass);
10429 MonoReflectionMethod*
10430 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10433 MonoMethod *method, *inflated;
10434 MonoMethodInflated *imethod;
10435 MonoGenericContext tmp_context;
10436 MonoGenericInst *ginst;
10437 MonoType **type_argv;
10440 MONO_ARCH_SAVE_REGS;
10442 /*FIXME but this no longer should happen*/
10443 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10444 #ifndef DISABLE_REFLECTION_EMIT
10445 MonoReflectionMethodBuilder *mb = NULL;
10446 MonoReflectionTypeBuilder *tb;
10449 mb = (MonoReflectionMethodBuilder *) rmethod;
10450 tb = (MonoReflectionTypeBuilder *) mb->type;
10451 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10453 method = methodbuilder_to_mono_method (klass, mb);
10455 g_assert_not_reached ();
10459 method = rmethod->method;
10462 klass = method->klass;
10464 if (method->is_inflated)
10465 method = ((MonoMethodInflated *) method)->declaring;
10467 count = mono_method_signature (method)->generic_param_count;
10468 if (count != mono_array_length (types))
10471 type_argv = g_new0 (MonoType *, count);
10472 for (i = 0; i < count; i++) {
10473 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10474 type_argv [i] = mono_reflection_type_get_handle (garg);
10476 ginst = mono_metadata_get_generic_inst (count, type_argv);
10477 g_free (type_argv);
10479 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10480 tmp_context.method_inst = ginst;
10482 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10483 imethod = (MonoMethodInflated *) inflated;
10485 /*FIXME but I think this is no longer necessary*/
10486 if (method->klass->image->dynamic) {
10487 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10489 * This table maps metadata structures representing inflated methods/fields
10490 * to the reflection objects representing their generic definitions.
10492 mono_loader_lock ();
10493 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10494 mono_loader_unlock ();
10497 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10498 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10500 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10503 #ifndef DISABLE_REFLECTION_EMIT
10505 static MonoMethod *
10506 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10508 MonoMethodInflated *imethod;
10509 MonoGenericContext *context;
10513 * With generic code sharing the klass might not be inflated.
10514 * This can happen because classes inflated with their own
10515 * type arguments are "normalized" to the uninflated class.
10517 if (!klass->generic_class)
10520 context = mono_class_get_context (klass);
10522 if (klass->method.count && klass->methods) {
10523 /* Find the already created inflated method */
10524 for (i = 0; i < klass->method.count; ++i) {
10525 g_assert (klass->methods [i]->is_inflated);
10526 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10529 g_assert (i < klass->method.count);
10530 imethod = (MonoMethodInflated*)klass->methods [i];
10532 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10535 if (method->is_generic && method->klass->image->dynamic) {
10536 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10538 mono_loader_lock ();
10539 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10540 mono_loader_unlock ();
10542 return (MonoMethod *) imethod;
10545 static MonoMethod *
10546 inflate_method (MonoReflectionType *type, MonoObject *obj)
10548 MonoMethod *method;
10551 MonoClass *type_class = mono_object_class (type);
10553 if (is_sre_generic_instance (type_class)) {
10554 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10555 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10556 } else if (is_sre_type_builder (type_class)) {
10557 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10558 } else if (type->type) {
10559 gklass = mono_class_from_mono_type (type->type);
10560 gklass = mono_class_get_generic_type_definition (gklass);
10562 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10565 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10566 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10567 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10569 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10570 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10571 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10572 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10573 method = ((MonoReflectionMethod *) obj)->method;
10575 method = NULL; /* prevent compiler warning */
10576 g_error ("can't handle type %s", obj->vtable->klass->name);
10579 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10582 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10584 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10585 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10588 MonoGenericClass *gclass;
10589 MonoDynamicGenericClass *dgclass;
10590 MonoClass *klass, *gklass;
10594 MONO_ARCH_SAVE_REGS;
10596 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10597 klass = mono_class_from_mono_type (gtype);
10598 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10599 gclass = gtype->data.generic_class;
10601 if (!gclass->is_dynamic)
10604 dgclass = (MonoDynamicGenericClass *) gclass;
10606 if (dgclass->initialized)
10609 gklass = gclass->container_class;
10610 mono_class_init (gklass);
10612 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10613 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10614 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10616 dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10617 dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10618 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10619 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10620 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10622 for (i = 0; i < dgclass->count_methods; i++) {
10623 MonoObject *obj = mono_array_get (methods, gpointer, i);
10625 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10628 for (i = 0; i < dgclass->count_ctors; i++) {
10629 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10631 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10634 for (i = 0; i < dgclass->count_fields; i++) {
10635 MonoObject *obj = mono_array_get (fields, gpointer, i);
10636 MonoClassField *field, *inflated_field = NULL;
10638 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10639 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10640 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10641 field = ((MonoReflectionField *) obj)->field;
10643 field = NULL; /* prevent compiler warning */
10644 g_assert_not_reached ();
10647 dgclass->fields [i] = *field;
10648 dgclass->fields [i].parent = klass;
10649 dgclass->fields [i].type = mono_class_inflate_generic_type (
10650 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10651 dgclass->field_generic_types [i] = field->type;
10652 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10653 dgclass->field_objects [i] = obj;
10655 if (inflated_field) {
10656 g_free (inflated_field);
10658 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10662 dgclass->initialized = TRUE;
10666 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10668 MonoDynamicGenericClass *dgclass;
10671 g_assert (gclass->is_dynamic);
10673 dgclass = (MonoDynamicGenericClass *)gclass;
10675 for (i = 0; i < dgclass->count_fields; ++i) {
10676 MonoClassField *field = dgclass->fields + i;
10677 mono_metadata_free_type (field->type);
10678 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10683 fix_partial_generic_class (MonoClass *klass)
10685 MonoClass *gklass = klass->generic_class->container_class;
10686 MonoDynamicGenericClass *dgclass;
10689 if (klass->wastypebuilder)
10692 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10693 if (klass->parent != gklass->parent) {
10695 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10696 if (mono_error_ok (&error)) {
10697 MonoClass *parent = mono_class_from_mono_type (parent_type);
10698 mono_metadata_free_type (parent_type);
10699 if (parent != klass->parent) {
10700 /*fool mono_class_setup_parent*/
10701 klass->supertypes = NULL;
10702 mono_class_setup_parent (klass, parent);
10705 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10706 mono_error_cleanup (&error);
10707 if (gklass->wastypebuilder)
10708 klass->wastypebuilder = TRUE;
10713 if (!dgclass->initialized)
10716 if (klass->method.count != gklass->method.count) {
10717 klass->method.count = gklass->method.count;
10718 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10720 for (i = 0; i < klass->method.count; i++) {
10721 klass->methods [i] = mono_class_inflate_generic_method_full (
10722 gklass->methods [i], klass, mono_class_get_context (klass));
10726 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10727 klass->interface_count = gklass->interface_count;
10728 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10729 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10731 for (i = 0; i < gklass->interface_count; ++i) {
10732 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10733 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10734 mono_metadata_free_type (iface_type);
10736 ensure_runtime_vtable (klass->interfaces [i]);
10738 klass->interfaces_inited = 1;
10741 if (klass->field.count != gklass->field.count) {
10742 klass->field.count = gklass->field.count;
10743 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10745 for (i = 0; i < klass->field.count; i++) {
10746 klass->fields [i] = gklass->fields [i];
10747 klass->fields [i].parent = klass;
10748 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10752 /*We can only finish with this klass once it's parent has as well*/
10753 if (gklass->wastypebuilder)
10754 klass->wastypebuilder = TRUE;
10759 ensure_generic_class_runtime_vtable (MonoClass *klass)
10761 MonoClass *gklass = klass->generic_class->container_class;
10763 ensure_runtime_vtable (gklass);
10765 fix_partial_generic_class (klass);
10769 ensure_runtime_vtable (MonoClass *klass)
10771 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10774 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10777 ensure_runtime_vtable (klass->parent);
10780 num = tb->ctors? mono_array_length (tb->ctors): 0;
10781 num += tb->num_methods;
10782 klass->method.count = num;
10783 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10784 num = tb->ctors? mono_array_length (tb->ctors): 0;
10785 for (i = 0; i < num; ++i)
10786 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10787 num = tb->num_methods;
10789 for (i = 0; i < num; ++i)
10790 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10792 if (tb->interfaces) {
10793 klass->interface_count = mono_array_length (tb->interfaces);
10794 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10795 for (i = 0; i < klass->interface_count; ++i) {
10796 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10797 klass->interfaces [i] = mono_class_from_mono_type (iface);
10798 ensure_runtime_vtable (klass->interfaces [i]);
10800 klass->interfaces_inited = 1;
10802 } else if (klass->generic_class){
10803 ensure_generic_class_runtime_vtable (klass);
10806 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10808 for (i = 0; i < klass->method.count; ++i) {
10809 MonoMethod *im = klass->methods [i];
10810 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10811 im->slot = slot_num++;
10814 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10815 mono_class_setup_interface_offsets (klass);
10816 mono_class_setup_interface_id (klass);
10820 * The generic vtable is needed even if image->run is not set since some
10821 * runtime code like ves_icall_Type_GetMethodsByName depends on
10822 * method->slot being defined.
10826 * tb->methods could not be freed since it is used for determining
10827 * overrides during dynamic vtable construction.
10832 mono_reflection_method_get_handle (MonoObject *method)
10834 MonoClass *class = mono_object_class (method);
10835 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10836 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10837 return sr_method->method;
10839 if (is_sre_method_builder (class)) {
10840 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10841 return mb->mhandle;
10843 if (is_sre_method_on_tb_inst (class)) {
10844 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10845 MonoMethod *result;
10846 /*FIXME move this to a proper method and unify with resolve_object*/
10847 if (m->method_args) {
10848 result = mono_reflection_method_on_tb_inst_get_handle (m);
10850 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10851 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10852 MonoMethod *mono_method;
10854 if (is_sre_method_builder (mono_object_class (m->mb)))
10855 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10856 else if (is_sr_mono_method (mono_object_class (m->mb)))
10857 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10859 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)));
10861 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10866 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10871 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10873 MonoReflectionTypeBuilder *tb;
10877 *num_overrides = 0;
10879 g_assert (klass->image->dynamic);
10881 if (!mono_class_get_ref_info (klass))
10884 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10886 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10890 for (i = 0; i < tb->num_methods; ++i) {
10891 MonoReflectionMethodBuilder *mb =
10892 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10893 if (mb->override_method)
10899 *overrides = g_new0 (MonoMethod*, onum * 2);
10902 for (i = 0; i < tb->num_methods; ++i) {
10903 MonoReflectionMethodBuilder *mb =
10904 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10905 if (mb->override_method) {
10906 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10907 (*overrides) [onum * 2 + 1] = mb->mhandle;
10909 g_assert (mb->mhandle);
10916 *num_overrides = onum;
10920 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10922 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10923 MonoReflectionFieldBuilder *fb;
10924 MonoClassField *field;
10925 MonoImage *image = klass->image;
10926 const char *p, *p2;
10928 guint32 len, idx, real_size = 0;
10930 klass->field.count = tb->num_fields;
10931 klass->field.first = 0;
10933 mono_error_init (error);
10935 if (tb->class_size) {
10936 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10937 klass->packing_size = tb->packing_size;
10938 real_size = klass->instance_size + tb->class_size;
10941 if (!klass->field.count) {
10942 klass->instance_size = MAX (klass->instance_size, real_size);
10946 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10947 mono_class_alloc_ext (klass);
10948 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10950 This is, guess what, a hack.
10951 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10952 On the static path no field class is resolved, only types are built. This is the right thing to do
10954 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10956 klass->size_inited = 1;
10958 for (i = 0; i < klass->field.count; ++i) {
10959 fb = mono_array_get (tb->fields, gpointer, i);
10960 field = &klass->fields [i];
10961 field->name = mono_string_to_utf8_image (image, fb->name, error);
10962 if (!mono_error_ok (error))
10965 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10966 field->type->attrs = fb->attrs;
10968 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10970 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10971 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10972 if (fb->offset != -1)
10973 field->offset = fb->offset;
10974 field->parent = klass;
10975 fb->handle = field;
10976 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10978 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10979 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10981 if (fb->def_value) {
10982 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10983 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10984 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10985 /* Copy the data from the blob since it might get realloc-ed */
10986 p = assembly->blob.data + idx;
10987 len = mono_metadata_decode_blob_size (p, &p2);
10989 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10990 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10994 klass->instance_size = MAX (klass->instance_size, real_size);
10995 mono_class_layout_fields (klass);
10999 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11001 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11002 MonoReflectionPropertyBuilder *pb;
11003 MonoImage *image = klass->image;
11004 MonoProperty *properties;
11007 mono_error_init (error);
11010 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11012 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11013 klass->ext->property.first = 0;
11015 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11016 klass->ext->properties = properties;
11017 for (i = 0; i < klass->ext->property.count; ++i) {
11018 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11019 properties [i].parent = klass;
11020 properties [i].attrs = pb->attrs;
11021 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11022 if (!mono_error_ok (error))
11024 if (pb->get_method)
11025 properties [i].get = pb->get_method->mhandle;
11026 if (pb->set_method)
11027 properties [i].set = pb->set_method->mhandle;
11029 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11030 if (pb->def_value) {
11032 const char *p, *p2;
11033 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11034 if (!klass->ext->prop_def_values)
11035 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11036 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11037 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11038 /* Copy the data from the blob since it might get realloc-ed */
11039 p = assembly->blob.data + idx;
11040 len = mono_metadata_decode_blob_size (p, &p2);
11042 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11043 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11048 MonoReflectionEvent *
11049 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11051 MonoEvent *event = g_new0 (MonoEvent, 1);
11054 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11056 event->parent = klass;
11057 event->attrs = eb->attrs;
11058 event->name = mono_string_to_utf8 (eb->name);
11059 if (eb->add_method)
11060 event->add = eb->add_method->mhandle;
11061 if (eb->remove_method)
11062 event->remove = eb->remove_method->mhandle;
11063 if (eb->raise_method)
11064 event->raise = eb->raise_method->mhandle;
11066 #ifndef MONO_SMALL_CONFIG
11067 if (eb->other_methods) {
11069 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11070 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11071 MonoReflectionMethodBuilder *mb =
11072 mono_array_get (eb->other_methods,
11073 MonoReflectionMethodBuilder*, j);
11074 event->other [j] = mb->mhandle;
11079 return mono_event_get_object (mono_object_domain (tb), klass, event);
11083 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11085 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11086 MonoReflectionEventBuilder *eb;
11087 MonoImage *image = klass->image;
11091 mono_error_init (error);
11094 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11096 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11097 klass->ext->event.first = 0;
11099 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11100 klass->ext->events = events;
11101 for (i = 0; i < klass->ext->event.count; ++i) {
11102 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11103 events [i].parent = klass;
11104 events [i].attrs = eb->attrs;
11105 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11106 if (!mono_error_ok (error))
11108 if (eb->add_method)
11109 events [i].add = eb->add_method->mhandle;
11110 if (eb->remove_method)
11111 events [i].remove = eb->remove_method->mhandle;
11112 if (eb->raise_method)
11113 events [i].raise = eb->raise_method->mhandle;
11115 #ifndef MONO_SMALL_CONFIG
11116 if (eb->other_methods) {
11118 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11119 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11120 MonoReflectionMethodBuilder *mb =
11121 mono_array_get (eb->other_methods,
11122 MonoReflectionMethodBuilder*, j);
11123 events [i].other [j] = mb->mhandle;
11127 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11132 remove_instantiations_of_and_ensure_contents (gpointer key,
11134 gpointer user_data)
11136 MonoType *type = (MonoType*)key;
11137 MonoClass *klass = (MonoClass*)user_data;
11139 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11140 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11147 check_array_for_usertypes (MonoArray *arr)
11154 for (i = 0; i < mono_array_length (arr); ++i)
11155 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11158 MonoReflectionType*
11159 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11163 MonoDomain* domain;
11164 MonoReflectionType* res;
11167 MONO_ARCH_SAVE_REGS;
11169 domain = mono_object_domain (tb);
11170 klass = mono_class_from_mono_type (tb->type.type);
11173 * Check for user defined Type subclasses.
11175 RESOLVE_TYPE (tb->parent);
11176 check_array_for_usertypes (tb->interfaces);
11178 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11179 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11181 RESOLVE_TYPE (fb->type);
11182 check_array_for_usertypes (fb->modreq);
11183 check_array_for_usertypes (fb->modopt);
11184 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11185 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11190 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11191 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11193 RESOLVE_TYPE (mb->rtype);
11194 check_array_for_usertypes (mb->return_modreq);
11195 check_array_for_usertypes (mb->return_modopt);
11196 check_array_for_usertypes (mb->parameters);
11197 if (mb->param_modreq)
11198 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11199 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11200 if (mb->param_modopt)
11201 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11202 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11207 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11208 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11210 check_array_for_usertypes (mb->parameters);
11211 if (mb->param_modreq)
11212 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11213 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11214 if (mb->param_modopt)
11215 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11216 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11221 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11224 * we need to lock the domain because the lock will be taken inside
11225 * So, we need to keep the locking order correct.
11227 mono_loader_lock ();
11228 mono_domain_lock (domain);
11229 if (klass->wastypebuilder) {
11230 mono_domain_unlock (domain);
11231 mono_loader_unlock ();
11232 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11235 * Fields to set in klass:
11236 * the various flags: delegate/unicode/contextbound etc.
11238 klass->flags = tb->attrs;
11239 klass->has_cctor = 1;
11240 klass->has_finalize = 1;
11241 klass->has_finalize_inited = 1;
11243 /* fool mono_class_setup_parent */
11244 klass->supertypes = NULL;
11245 mono_class_setup_parent (klass, klass->parent);
11246 mono_class_setup_mono_type (klass);
11249 if (!((MonoDynamicImage*)klass->image)->run) {
11250 if (klass->generic_container) {
11251 /* FIXME: The code below can't handle generic classes */
11252 klass->wastypebuilder = TRUE;
11253 mono_loader_unlock ();
11254 mono_domain_unlock (domain);
11255 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11260 /* enums are done right away */
11261 if (!klass->enumtype)
11262 ensure_runtime_vtable (klass);
11264 if (tb->subtypes) {
11265 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11266 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11267 mono_class_alloc_ext (klass);
11268 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)));
11272 klass->nested_classes_inited = TRUE;
11274 /* fields and object layout */
11275 if (klass->parent) {
11276 if (!klass->parent->size_inited)
11277 mono_class_init (klass->parent);
11278 klass->instance_size = klass->parent->instance_size;
11279 klass->sizes.class_size = 0;
11280 klass->min_align = klass->parent->min_align;
11281 /* if the type has no fields we won't call the field_setup
11282 * routine which sets up klass->has_references.
11284 klass->has_references |= klass->parent->has_references;
11286 klass->instance_size = sizeof (MonoObject);
11287 klass->min_align = 1;
11290 /* FIXME: handle packing_size and instance_size */
11291 typebuilder_setup_fields (klass, &error);
11292 if (!mono_error_ok (&error))
11294 typebuilder_setup_properties (klass, &error);
11295 if (!mono_error_ok (&error))
11298 typebuilder_setup_events (klass, &error);
11299 if (!mono_error_ok (&error))
11302 klass->wastypebuilder = TRUE;
11305 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11306 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11307 * we want to return normal System.MonoType objects, so clear these out from the cache.
11309 * Together with this we must ensure the contents of all instances to match the created type.
11311 if (domain->type_hash && klass->generic_container)
11312 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11314 mono_domain_unlock (domain);
11315 mono_loader_unlock ();
11317 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11318 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11319 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11322 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11323 g_assert (res != (MonoReflectionType*)tb);
11328 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11329 klass->wastypebuilder = TRUE;
11330 mono_domain_unlock (domain);
11331 mono_loader_unlock ();
11332 mono_error_raise_exception (&error);
11337 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11339 MonoGenericParamFull *param;
11344 MONO_ARCH_SAVE_REGS;
11346 image = &gparam->tbuilder->module->dynamic_image->image;
11348 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11350 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11351 g_assert (mono_error_ok (&error));
11352 param->param.num = gparam->index;
11354 if (gparam->mbuilder) {
11355 if (!gparam->mbuilder->generic_container) {
11356 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11357 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11358 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11359 gparam->mbuilder->generic_container->is_method = TRUE;
11361 * Cannot set owner.method, since the MonoMethod is not created yet.
11362 * Set the image field instead, so type_in_image () works.
11364 gparam->mbuilder->generic_container->image = klass->image;
11366 param->param.owner = gparam->mbuilder->generic_container;
11367 } else if (gparam->tbuilder) {
11368 if (!gparam->tbuilder->generic_container) {
11369 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11370 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11371 gparam->tbuilder->generic_container->owner.klass = klass;
11373 param->param.owner = gparam->tbuilder->generic_container;
11376 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11378 gparam->type.type = &pklass->byval_arg;
11380 mono_class_set_ref_info (pklass, gparam);
11381 mono_image_lock (image);
11382 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11383 mono_image_unlock (image);
11387 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11389 MonoReflectionModuleBuilder *module = sig->module;
11390 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11391 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11396 check_array_for_usertypes (sig->arguments);
11398 sigbuffer_init (&buf, 32);
11400 sigbuffer_add_value (&buf, 0x07);
11401 sigbuffer_add_value (&buf, na);
11402 if (assembly != NULL){
11403 for (i = 0; i < na; ++i) {
11404 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11405 encode_reflection_type (assembly, type, &buf);
11409 buflen = buf.p - buf.buf;
11410 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11411 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11412 sigbuffer_free (&buf);
11418 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11420 MonoDynamicImage *assembly = sig->module->dynamic_image;
11421 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11426 check_array_for_usertypes (sig->arguments);
11428 sigbuffer_init (&buf, 32);
11430 sigbuffer_add_value (&buf, 0x06);
11431 for (i = 0; i < na; ++i) {
11432 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11433 encode_reflection_type (assembly, type, &buf);
11436 buflen = buf.p - buf.buf;
11437 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11438 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11439 sigbuffer_free (&buf);
11445 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11447 ReflectionMethodBuilder rmb;
11448 MonoMethodSignature *sig;
11453 sig = dynamic_method_to_signature (mb);
11455 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11458 * Resolve references.
11461 * Every second entry in the refs array is reserved for storing handle_class,
11462 * which is needed by the ldtoken implementation in the JIT.
11464 rmb.nrefs = mb->nrefs;
11465 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11466 for (i = 0; i < mb->nrefs; i += 2) {
11467 MonoClass *handle_class;
11469 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11471 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11472 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11474 * The referenced DynamicMethod should already be created by the managed
11475 * code, except in the case of circular references. In that case, we store
11476 * method in the refs array, and fix it up later when the referenced
11477 * DynamicMethod is created.
11479 if (method->mhandle) {
11480 ref = method->mhandle;
11482 /* FIXME: GC object stored in unmanaged memory */
11485 /* FIXME: GC object stored in unmanaged memory */
11486 method->referenced_by = g_slist_append (method->referenced_by, mb);
11488 handle_class = mono_defaults.methodhandle_class;
11490 MonoException *ex = NULL;
11491 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11493 ex = mono_get_exception_type_load (NULL, NULL);
11494 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11495 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11499 mono_raise_exception (ex);
11504 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11505 rmb.refs [i + 1] = handle_class;
11508 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11510 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11512 /* Fix up refs entries pointing at us */
11513 for (l = mb->referenced_by; l; l = l->next) {
11514 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11515 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11518 g_assert (method->mhandle);
11520 data = (gpointer*)wrapper->method_data;
11521 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11522 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11523 data [i + 1] = mb->mhandle;
11526 g_slist_free (mb->referenced_by);
11530 /* ilgen is no longer needed */
11534 #endif /* DISABLE_REFLECTION_EMIT */
11537 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11542 mono_runtime_free_method (
11543 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11548 * mono_reflection_is_valid_dynamic_token:
11550 * Returns TRUE if token is valid.
11554 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11556 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11559 MonoMethodSignature *
11560 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11562 MonoMethodSignature *sig;
11563 g_assert (image->dynamic);
11565 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11569 return mono_method_signature (method);
11572 #ifndef DISABLE_REFLECTION_EMIT
11575 * mono_reflection_lookup_dynamic_token:
11577 * Finish the Builder object pointed to by TOKEN and return the corresponding
11578 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11579 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11582 * LOCKING: Take the loader lock
11585 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11587 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11591 mono_loader_lock ();
11592 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11593 mono_loader_unlock ();
11596 g_error ("Could not find required dynamic token 0x%08x", token);
11602 handle_class = &klass;
11603 return resolve_object (image, obj, handle_class, context);
11607 * ensure_complete_type:
11609 * Ensure that KLASS is completed if it is a dynamic type, or references
11613 ensure_complete_type (MonoClass *klass)
11615 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11616 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11618 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11620 // Asserting here could break a lot of code
11621 //g_assert (klass->wastypebuilder);
11624 if (klass->generic_class) {
11625 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11628 for (i = 0; i < inst->type_argc; ++i) {
11629 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11635 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11637 gpointer result = NULL;
11639 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11640 result = mono_string_intern ((MonoString*)obj);
11641 *handle_class = mono_defaults.string_class;
11643 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11644 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11645 MonoClass *mc = mono_class_from_mono_type (type);
11646 if (!mono_class_init (mc))
11647 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11650 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11651 result = mono_class_from_mono_type (inflated);
11652 mono_metadata_free_type (inflated);
11654 result = mono_class_from_mono_type (type);
11656 *handle_class = mono_defaults.typehandle_class;
11658 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11659 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11660 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11661 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11662 result = ((MonoReflectionMethod*)obj)->method;
11664 result = mono_class_inflate_generic_method (result, context);
11665 *handle_class = mono_defaults.methodhandle_class;
11667 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11668 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11669 result = mb->mhandle;
11671 /* Type is not yet created */
11672 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11674 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11677 * Hopefully this has been filled in by calling CreateType() on the
11681 * TODO: This won't work if the application finishes another
11682 * TypeBuilder instance instead of this one.
11684 result = mb->mhandle;
11687 result = mono_class_inflate_generic_method (result, context);
11688 *handle_class = mono_defaults.methodhandle_class;
11689 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11690 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11692 result = cb->mhandle;
11694 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11696 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11697 result = cb->mhandle;
11700 result = mono_class_inflate_generic_method (result, context);
11701 *handle_class = mono_defaults.methodhandle_class;
11702 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11703 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11705 ensure_complete_type (field->parent);
11707 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11708 MonoClass *class = mono_class_from_mono_type (inflated);
11709 MonoClassField *inflated_field;
11710 gpointer iter = NULL;
11711 mono_metadata_free_type (inflated);
11712 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11713 if (!strcmp (field->name, inflated_field->name))
11716 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11717 result = inflated_field;
11721 *handle_class = mono_defaults.fieldhandle_class;
11723 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11724 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11725 result = fb->handle;
11728 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11730 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11731 result = fb->handle;
11734 if (fb->handle && fb->handle->parent->generic_container) {
11735 MonoClass *klass = fb->handle->parent;
11736 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11737 MonoClass *inflated = mono_class_from_mono_type (type);
11739 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11741 mono_metadata_free_type (type);
11743 *handle_class = mono_defaults.fieldhandle_class;
11744 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11745 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11746 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11749 klass = type->data.klass;
11750 if (klass->wastypebuilder) {
11751 /* Already created */
11755 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11756 result = type->data.klass;
11759 *handle_class = mono_defaults.typehandle_class;
11760 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11761 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11762 MonoMethodSignature *sig;
11765 if (helper->arguments)
11766 nargs = mono_array_length (helper->arguments);
11770 sig = mono_metadata_signature_alloc (image, nargs);
11771 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11772 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11774 if (helper->unmanaged_call_conv) { /* unmanaged */
11775 sig->call_convention = helper->unmanaged_call_conv - 1;
11776 sig->pinvoke = TRUE;
11777 } else if (helper->call_conv & 0x02) {
11778 sig->call_convention = MONO_CALL_VARARG;
11780 sig->call_convention = MONO_CALL_DEFAULT;
11783 sig->param_count = nargs;
11784 /* TODO: Copy type ? */
11785 sig->ret = helper->return_type->type;
11786 for (i = 0; i < nargs; ++i)
11787 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11790 *handle_class = NULL;
11791 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11792 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11793 /* Already created by the managed code */
11794 g_assert (method->mhandle);
11795 result = method->mhandle;
11796 *handle_class = mono_defaults.methodhandle_class;
11797 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11798 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11799 type = mono_class_inflate_generic_type (type, context);
11800 result = mono_class_from_mono_type (type);
11801 *handle_class = mono_defaults.typehandle_class;
11803 mono_metadata_free_type (type);
11804 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11805 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11806 type = mono_class_inflate_generic_type (type, context);
11807 result = mono_class_from_mono_type (type);
11808 *handle_class = mono_defaults.typehandle_class;
11810 mono_metadata_free_type (type);
11811 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11812 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11813 MonoClass *inflated;
11815 MonoClassField *field;
11817 if (is_sre_field_builder (mono_object_class (f->fb)))
11818 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11819 else if (is_sr_mono_field (mono_object_class (f->fb)))
11820 field = ((MonoReflectionField*)f->fb)->field;
11822 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)));
11824 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11825 inflated = mono_class_from_mono_type (type);
11827 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11828 ensure_complete_type (field->parent);
11830 mono_metadata_free_type (type);
11831 *handle_class = mono_defaults.fieldhandle_class;
11832 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11833 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11834 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11835 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11836 MonoMethod *method;
11838 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11839 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11840 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11841 method = ((MonoReflectionMethod *)c->cb)->method;
11843 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)));
11845 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11846 *handle_class = mono_defaults.methodhandle_class;
11847 mono_metadata_free_type (type);
11848 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11849 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11850 if (m->method_args) {
11851 result = mono_reflection_method_on_tb_inst_get_handle (m);
11853 result = mono_class_inflate_generic_method (result, context);
11855 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11856 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11857 MonoMethod *method;
11859 if (is_sre_method_builder (mono_object_class (m->mb)))
11860 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11861 else if (is_sr_mono_method (mono_object_class (m->mb)))
11862 method = ((MonoReflectionMethod *)m->mb)->method;
11864 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)));
11866 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11867 mono_metadata_free_type (type);
11869 *handle_class = mono_defaults.methodhandle_class;
11870 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11871 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11874 MonoMethod *method;
11878 mtype = mono_reflection_type_get_handle (m->parent);
11879 klass = mono_class_from_mono_type (mtype);
11881 /* Find the method */
11883 name = mono_string_to_utf8 (m->name);
11885 while ((method = mono_class_get_methods (klass, &iter))) {
11886 if (!strcmp (method->name, name))
11893 // FIXME: Check parameters/return value etc. match
11896 *handle_class = mono_defaults.methodhandle_class;
11897 } else if (is_sre_array (mono_object_get_class(obj)) ||
11898 is_sre_byref (mono_object_get_class(obj)) ||
11899 is_sre_pointer (mono_object_get_class(obj))) {
11900 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11901 MonoType *type = mono_reflection_type_get_handle (ref_type);
11902 result = mono_class_from_mono_type (type);
11903 *handle_class = mono_defaults.typehandle_class;
11905 g_print ("%s\n", obj->vtable->klass->name);
11906 g_assert_not_reached ();
11911 #else /* DISABLE_REFLECTION_EMIT */
11914 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11916 g_assert_not_reached ();
11921 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11923 g_assert_not_reached ();
11927 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11929 g_assert_not_reached ();
11933 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11935 g_assert_not_reached ();
11939 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11941 g_assert_not_reached ();
11945 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11947 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11951 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11953 g_assert_not_reached ();
11957 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11959 g_assert_not_reached ();
11962 MonoReflectionModule *
11963 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11965 g_assert_not_reached ();
11970 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11972 g_assert_not_reached ();
11977 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11979 g_assert_not_reached ();
11984 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11985 gboolean create_open_instance, gboolean register_token)
11987 g_assert_not_reached ();
11992 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11997 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11998 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12001 g_assert_not_reached ();
12005 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12008 *num_overrides = 0;
12011 MonoReflectionEvent *
12012 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12014 g_assert_not_reached ();
12018 MonoReflectionType*
12019 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12021 g_assert_not_reached ();
12026 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12028 g_assert_not_reached ();
12032 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12034 g_assert_not_reached ();
12039 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12041 g_assert_not_reached ();
12046 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12051 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12057 mono_reflection_type_get_handle (MonoReflectionType* ref)
12065 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12067 g_assert_not_reached ();
12070 #endif /* DISABLE_REFLECTION_EMIT */
12072 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12073 const static guint32 declsec_flags_map[] = {
12074 0x00000000, /* empty */
12075 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12076 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12077 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12078 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12079 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12080 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12081 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12082 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12083 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12084 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12085 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12086 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12087 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12088 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12089 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12090 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12091 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12092 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12096 * Returns flags that includes all available security action associated to the handle.
12097 * @token: metadata token (either for a class or a method)
12098 * @image: image where resides the metadata.
12101 mono_declsec_get_flags (MonoImage *image, guint32 token)
12103 int index = mono_metadata_declsec_from_index (image, token);
12104 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12105 guint32 result = 0;
12109 /* HasSecurity can be present for other, not specially encoded, attributes,
12110 e.g. SuppressUnmanagedCodeSecurityAttribute */
12114 for (i = index; i < t->rows; i++) {
12115 guint32 cols [MONO_DECL_SECURITY_SIZE];
12117 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12118 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12121 action = cols [MONO_DECL_SECURITY_ACTION];
12122 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12123 result |= declsec_flags_map [action];
12125 g_assert_not_reached ();
12132 * Get the security actions (in the form of flags) associated with the specified method.
12134 * @method: The method for which we want the declarative security flags.
12135 * Return the declarative security flags for the method (only).
12137 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12138 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12141 mono_declsec_flags_from_method (MonoMethod *method)
12143 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12144 /* FIXME: No cache (for the moment) */
12145 guint32 idx = mono_method_get_index (method);
12146 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12147 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12148 return mono_declsec_get_flags (method->klass->image, idx);
12154 * Get the security actions (in the form of flags) associated with the specified class.
12156 * @klass: The class for which we want the declarative security flags.
12157 * Return the declarative security flags for the class.
12159 * Note: We cache the flags inside the MonoClass structure as this will get
12160 * called very often (at least for each method).
12163 mono_declsec_flags_from_class (MonoClass *klass)
12165 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12166 if (!klass->ext || !klass->ext->declsec_flags) {
12169 idx = mono_metadata_token_index (klass->type_token);
12170 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12171 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12172 mono_loader_lock ();
12173 mono_class_alloc_ext (klass);
12174 mono_loader_unlock ();
12175 /* we cache the flags on classes */
12176 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12178 return klass->ext->declsec_flags;
12184 * Get the security actions (in the form of flags) associated with the specified assembly.
12186 * @assembly: The assembly for which we want the declarative security flags.
12187 * Return the declarative security flags for the assembly.
12190 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12192 guint32 idx = 1; /* there is only one assembly */
12193 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12194 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12195 return mono_declsec_get_flags (assembly->image, idx);
12200 * Fill actions for the specific index (which may either be an encoded class token or
12201 * an encoded method token) from the metadata image.
12202 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12205 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12206 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12208 MonoBoolean result = FALSE;
12210 guint32 cols [MONO_DECL_SECURITY_SIZE];
12211 int index = mono_metadata_declsec_from_index (image, token);
12214 t = &image->tables [MONO_TABLE_DECLSECURITY];
12215 for (i = index; i < t->rows; i++) {
12216 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12218 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12221 /* if present only replace (class) permissions with method permissions */
12222 /* if empty accept either class or method permissions */
12223 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12224 if (!actions->demand.blob) {
12225 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12226 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12227 actions->demand.blob = (char*) (blob + 2);
12228 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12231 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12232 if (!actions->noncasdemand.blob) {
12233 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12234 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12235 actions->noncasdemand.blob = (char*) (blob + 2);
12236 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12239 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12240 if (!actions->demandchoice.blob) {
12241 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12242 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12243 actions->demandchoice.blob = (char*) (blob + 2);
12244 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12254 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12255 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12257 guint32 idx = mono_metadata_token_index (klass->type_token);
12258 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12259 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12260 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12264 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12265 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12267 guint32 idx = mono_method_get_index (method);
12268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12269 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12270 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12274 * Collect all actions (that requires to generate code in mini) assigned for
12275 * the specified method.
12276 * Note: Don't use the content of actions if the function return FALSE.
12279 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12281 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12282 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12283 MonoBoolean result = FALSE;
12286 /* quick exit if no declarative security is present in the metadata */
12287 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12290 /* we want the original as the wrapper is "free" of the security informations */
12291 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12292 method = mono_marshal_method_from_wrapper (method);
12297 /* First we look for method-level attributes */
12298 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12299 mono_class_init (method->klass);
12300 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12302 result = mono_declsec_get_method_demands_params (method, demands,
12303 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12306 /* Here we use (or create) the class declarative cache to look for demands */
12307 flags = mono_declsec_flags_from_class (method->klass);
12308 if (flags & mask) {
12310 mono_class_init (method->klass);
12311 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12313 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12314 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12317 /* The boolean return value is used as a shortcut in case nothing needs to
12318 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12324 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12326 * Note: Don't use the content of actions if the function return FALSE.
12329 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12331 MonoBoolean result = FALSE;
12334 /* quick exit if no declarative security is present in the metadata */
12335 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12338 /* we want the original as the wrapper is "free" of the security informations */
12339 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12340 method = mono_marshal_method_from_wrapper (method);
12345 /* results are independant - zeroize both */
12346 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12347 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12349 /* First we look for method-level attributes */
12350 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12351 mono_class_init (method->klass);
12353 result = mono_declsec_get_method_demands_params (method, cmethod,
12354 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12357 /* Here we use (or create) the class declarative cache to look for demands */
12358 flags = mono_declsec_flags_from_class (method->klass);
12359 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12360 mono_class_init (method->klass);
12362 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12363 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12370 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12372 * @klass The inherited class - this is the class that provides the security check (attributes)
12374 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12376 * Note: Don't use the content of actions if the function return FALSE.
12379 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12381 MonoBoolean result = FALSE;
12384 /* quick exit if no declarative security is present in the metadata */
12385 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12388 /* Here we use (or create) the class declarative cache to look for demands */
12389 flags = mono_declsec_flags_from_class (klass);
12390 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12391 mono_class_init (klass);
12392 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12394 result |= mono_declsec_get_class_demands_params (klass, demands,
12395 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12402 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12404 * Note: Don't use the content of actions if the function return FALSE.
12407 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12409 /* quick exit if no declarative security is present in the metadata */
12410 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12413 /* we want the original as the wrapper is "free" of the security informations */
12414 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12415 method = mono_marshal_method_from_wrapper (method);
12420 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12421 mono_class_init (method->klass);
12422 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12424 return mono_declsec_get_method_demands_params (method, demands,
12425 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12432 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12434 guint32 cols [MONO_DECL_SECURITY_SIZE];
12438 int index = mono_metadata_declsec_from_index (image, token);
12442 t = &image->tables [MONO_TABLE_DECLSECURITY];
12443 for (i = index; i < t->rows; i++) {
12444 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12446 /* shortcut - index are ordered */
12447 if (token != cols [MONO_DECL_SECURITY_PARENT])
12450 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12451 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12452 entry->blob = (char*) (metadata + 2);
12453 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12462 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12464 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12465 guint32 idx = mono_method_get_index (method);
12466 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12467 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12468 return get_declsec_action (method->klass->image, idx, action, entry);
12474 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12477 guint32 flags = mono_declsec_flags_from_class (klass);
12478 if (declsec_flags_map [action] & flags) {
12479 guint32 idx = mono_metadata_token_index (klass->type_token);
12480 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12481 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12482 return get_declsec_action (klass->image, idx, action, entry);
12488 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12490 guint32 idx = 1; /* there is only one assembly */
12491 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12492 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12494 return get_declsec_action (assembly->image, idx, action, entry);
12498 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12500 MonoObject *res, *exc;
12502 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12503 static MonoMethod *method = NULL;
12505 if (!System_Reflection_Emit_TypeBuilder) {
12506 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12507 g_assert (System_Reflection_Emit_TypeBuilder);
12509 if (method == NULL) {
12510 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12515 * The result of mono_type_get_object () might be a System.MonoType but we
12516 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12518 g_assert (mono_class_get_ref_info (klass));
12519 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12521 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12523 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12527 return *(MonoBoolean*)mono_object_unbox (res);